| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // This file is part of Bembel, the higher order C++ boundary element library. | ||
| 2 | // | ||
| 3 | // Copyright (C) 2024 see <http://www.bembel.eu> | ||
| 4 | // | ||
| 5 | // It was written as part of a cooperation of J. Doelz, H. Harbrecht, S. Kurz, | ||
| 6 | // M. Multerer, S. Schoeps, and F. Wolf at Technische Universitaet Darmstadt, | ||
| 7 | // Universitaet Basel, and Universita della Svizzera italiana, Lugano. This | ||
| 8 | // source code is subject to the GNU General Public License version 3 and | ||
| 9 | // provided WITHOUT ANY WARRANTY, see <http://www.bembel.eu> for further | ||
| 10 | // information. | ||
| 11 | |||
| 12 | #ifndef BEMBEL_SRC_GEOMETRY_GEOMETRYIGS_HPP_ | ||
| 13 | #define BEMBEL_SRC_GEOMETRY_GEOMETRYIGS_HPP_ | ||
| 14 | |||
| 15 | namespace Bembel { | ||
| 16 | |||
| 17 | /** | ||
| 18 | * \ingroup Geometry | ||
| 19 | * \brief loads geometry from IGES file. Note that the direction | ||
| 20 | *of the normals must be consistent. | ||
| 21 | * | ||
| 22 | * \param file_name path/filename pointing to the geometry file | ||
| 23 | * \return std::vector of NURBS::Patch describing geometry | ||
| 24 | */ | ||
| 25 | 1 | std::vector<Patch> LoadGeometryFileIGS(const std::string& file_name) noexcept { | |
| 26 | 1 | std::ifstream file; | |
| 27 | 1 | std::vector<int> patch_lines; | |
| 28 | 1 | file.open(file_name); | |
| 29 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (!file) { |
| 30 | ✗ | std::cerr << "File " << file_name << " doesn't exist!"; | |
| 31 | ✗ | exit(1); | |
| 32 | } | ||
| 33 | 1 | std::string row; | |
| 34 | 1 | getline(file, row); | |
| 35 | |||
| 36 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (row[72] != 'S') { |
| 37 | std::cerr << "Format of the file not supported! I assume that character 72 " | ||
| 38 | ✗ | "denotes the section"; | |
| 39 | ✗ | exit(1); | |
| 40 | } | ||
| 41 | // character 72 denotes the section and the information starts in Section D | ||
| 42 |
2/2✓ Branch 1 taken 7 times.
✓ Branch 2 taken 1 times.
|
8 | while (row[72] != 'D') { |
| 43 | 7 | getline(file, row); | |
| 44 |
1/2✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
|
7 | assert(!file.eof() && "End of file should not be found here!"); |
| 45 | } | ||
| 46 | |||
| 47 | // collect two lines info of each patch from Directory section | ||
| 48 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
|
3 | while (row[72] != 'P') { |
| 49 | 2 | std::stringstream iss; | |
| 50 | 2 | std::string word; | |
| 51 | 2 | std::vector<int> info1, info2; | |
| 52 | 2 | iss.str(row); | |
| 53 |
2/2✓ Branch 2 taken 20 times.
✓ Branch 3 taken 2 times.
|
22 | while (iss >> word) { |
| 54 | 20 | info1.push_back(std::stoi(word)); | |
| 55 | } | ||
| 56 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | assert(info1[0] == 128 && "Entry type must be NURBS surface!"); |
| 57 | // this info1 in not going to be used further | ||
| 58 | |||
| 59 | 2 | getline(file, row); | |
| 60 | 2 | iss.clear(); | |
| 61 | 2 | iss.str(row); | |
| 62 |
2/2✓ Branch 2 taken 14 times.
✓ Branch 3 taken 2 times.
|
16 | while (iss >> word) { |
| 63 | 14 | info2.push_back(std::stoi(word)); | |
| 64 | } | ||
| 65 | 2 | getline(file, row); | |
| 66 | // This entry denotes how many lines correspond to a patch | ||
| 67 | 2 | patch_lines.push_back(info2[3]); | |
| 68 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | assert(!file.eof() && "End of file should not be found here!"); |
| 69 | 2 | } | |
| 70 | |||
| 71 | // main loop over patches | ||
| 72 | 1 | std::vector<Patch> out; | |
| 73 | 1 | out.reserve(patch_lines.size()); | |
| 74 | 1 | const int number_of_patches = patch_lines.size(); | |
| 75 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | for (auto i = 0; i < number_of_patches; ++i) { |
| 76 | 2 | std::stringstream iss; | |
| 77 | 2 | std::string word; | |
| 78 | 2 | std::vector<double> data; | |
| 79 |
2/2✓ Branch 1 taken 69 times.
✓ Branch 2 taken 2 times.
|
71 | for (auto j = 0; j < patch_lines[i]; ++j) { |
| 80 | // characters 0 to 63 contain data | ||
| 81 | 69 | std::string raw_data = row.substr(0, 64); | |
| 82 | 69 | raw_data.erase(std::remove(raw_data.begin(), raw_data.end(), ' '), | |
| 83 | 69 | raw_data.end()); | |
| 84 | |||
| 85 | 69 | iss.str(raw_data); | |
| 86 |
2/2✓ Branch 2 taken 294 times.
✓ Branch 3 taken 69 times.
|
363 | while (std::getline(iss, word, ',')) { |
| 87 | 294 | data.push_back(atof(word.c_str())); | |
| 88 | } | ||
| 89 | 69 | iss.clear(); | |
| 90 | |||
| 91 | 69 | getline(file, row); | |
| 92 | 69 | } | |
| 93 | |||
| 94 | 2 | const int K1 = data[1]; | |
| 95 | 2 | const int K2 = data[2]; | |
| 96 | 2 | const int M1 = data[3]; | |
| 97 | 2 | const int M2 = data[4]; | |
| 98 | |||
| 99 | 2 | const int N1 = 1 + K1 - M1; | |
| 100 | 2 | const int N2 = 1 + K2 - M2; | |
| 101 | 2 | const int A = N1 + 2 * M1; | |
| 102 | 2 | const int B = N2 + 2 * M2; | |
| 103 | 2 | const int C = (1 + K1) * (1 + K2); | |
| 104 | |||
| 105 | // The data of the first entries is read and not needed any more | ||
| 106 | 2 | data.erase(data.begin(), data.begin() + 10); | |
| 107 | |||
| 108 | // the + 1 is necessary because the construct excludes the last iterator | ||
| 109 | 2 | std::vector<double> tempknt1(data.begin(), data.begin() + A + 1); | |
| 110 | 2 | std::vector<double> tempknt2(data.begin() + A + 1, | |
| 111 | 4 | data.begin() + A + B + 2); | |
| 112 | |||
| 113 | 2 | const int M = K2 + 1; | |
| 114 | 2 | const int N = K1 + 1; | |
| 115 | |||
| 116 | 2 | Eigen::MatrixXd weights(M, N); | |
| 117 | 2 | auto it_weights = data.begin() + A + B + 2; | |
| 118 |
2/2✓ Branch 2 taken 55 times.
✓ Branch 3 taken 2 times.
|
57 | for (auto entry = it_weights; entry != it_weights + C; ++entry) { |
| 119 | 55 | int index = entry - it_weights; | |
| 120 | 55 | weights((int)index / N, index % N) = *entry; | |
| 121 | } | ||
| 122 | |||
| 123 | 2 | Eigen::MatrixXd x_coordinates(M, N); | |
| 124 | 2 | Eigen::MatrixXd y_coordinates(M, N); | |
| 125 | 2 | Eigen::MatrixXd z_coordinates(M, N); | |
| 126 | 2 | auto it_points = data.begin() + A + B + C + 2; | |
| 127 |
2/2✓ Branch 2 taken 55 times.
✓ Branch 3 taken 2 times.
|
57 | for (auto entry = it_points; entry != it_points + 3 * C; entry += 3) { |
| 128 | 55 | int index = (int)(entry - it_points) / 3; | |
| 129 | 55 | x_coordinates((int)index / N, index % N) = *entry; | |
| 130 | 55 | y_coordinates((int)index / N, index % N) = *(entry + 1); | |
| 131 | 55 | z_coordinates((int)index / N, index % N) = *(entry + 2); | |
| 132 | } | ||
| 133 | |||
| 134 | // we need to transfer to homogeneous coordinates | ||
| 135 | 2 | x_coordinates = x_coordinates.cwiseProduct(weights); | |
| 136 | 2 | y_coordinates = y_coordinates.cwiseProduct(weights); | |
| 137 | 2 | z_coordinates = z_coordinates.cwiseProduct(weights); | |
| 138 | |||
| 139 | std::vector<Eigen::MatrixXd> tmp = {x_coordinates, y_coordinates, | ||
| 140 | 12 | z_coordinates, weights}; | |
| 141 | |||
| 142 | 2 | Bembel::Patch tempPatch; | |
| 143 | 2 | tempPatch.init_Patch(tmp, tempknt1, tempknt2); | |
| 144 | 2 | out.push_back(tempPatch); | |
| 145 | 2 | } | |
| 146 | 1 | file.close(); | |
| 147 | 1 | return out; | |
| 148 | 1 | } | |
| 149 | |||
| 150 | /** | ||
| 151 | * \ingroup Geometry | ||
| 152 | * \brief This function writes a given section to the specified file. | ||
| 153 | * | ||
| 154 | * \param file_name path/filename pointing to the geometry file | ||
| 155 | * \param section vector containing the lines to be written to the file | ||
| 156 | * \param section_char char to describe the section. Use 'S', 'G' or 'D' | ||
| 157 | */ | ||
| 158 | 2 | void writeSection(std::string file_name, | |
| 159 | const std::vector<std::string>& section, | ||
| 160 | const char section_char) { | ||
| 161 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | std::ofstream file(file_name, std::ios::app); |
| 162 |
2/2✓ Branch 4 taken 7 times.
✓ Branch 5 taken 2 times.
|
9 | for (auto it = section.begin(); it != section.end(); ++it) { |
| 163 |
1/2✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | const int index = std::distance(section.begin(), it); |
| 164 |
5/10✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 7 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 7 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 7 times.
✗ Branch 16 not taken.
|
7 | file << std::left << std::setw(72) << *it << section_char << std::right |
| 165 |
3/6✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 7 times.
✗ Branch 9 not taken.
|
7 | << std::setw(7) << index + 1 << "\n"; |
| 166 | } | ||
| 167 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | file.close(); |
| 168 | 4 | return; | |
| 169 | 2 | } | |
| 170 | |||
| 171 | /** | ||
| 172 | * \ingroup Geometry | ||
| 173 | * \brief This function writes a the parameter section of the IGES file. | ||
| 174 | * | ||
| 175 | * \param file_name path/filename pointing to the geometry file | ||
| 176 | * \param section vector containing the lines to be written to the file | ||
| 177 | * \param patch_idx index counting in uneven number | ||
| 178 | * \param start_count Start counting the lines with this index | ||
| 179 | * \return Last index of the line | ||
| 180 | */ | ||
| 181 | 2 | int writeParameterSection(std::string file_name, | |
| 182 | const std::vector<std::string>& section, | ||
| 183 | const int patch_idx, const int start_count) { | ||
| 184 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | std::ofstream file(file_name, std::ios::app); |
| 185 | 2 | int last_line = start_count; | |
| 186 |
2/2✓ Branch 3 taken 69 times.
✓ Branch 4 taken 2 times.
|
71 | for (auto it = section.begin(); it != section.end(); ++it) { |
| 187 |
3/6✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 69 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 69 times.
✗ Branch 10 not taken.
|
69 | file << std::left << std::setw(64) << *it |
| 188 |
4/8✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 69 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 69 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 69 times.
✗ Branch 12 not taken.
|
69 | << std::right << std::setw(8) << patch_idx << "P" |
| 189 |
4/8✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 69 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 69 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 69 times.
✗ Branch 12 not taken.
|
69 | << std::right << std::setw(7) << last_line << "\n"; |
| 190 | 69 | ++last_line; | |
| 191 | } | ||
| 192 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | file.close(); |
| 193 | 2 | return last_line; | |
| 194 | 2 | } | |
| 195 | |||
| 196 | /** | ||
| 197 | * \ingroup Geometry | ||
| 198 | * \brief Transform a vector of Data in a vector of lines with a specific | ||
| 199 | *length. | ||
| 200 | * | ||
| 201 | * \param data vector containing the entries written to the section | ||
| 202 | * \param linewidth Maximum length of the lines | ||
| 203 | * \return Vector with strings of each line. | ||
| 204 | */ | ||
| 205 | 3 | std::vector<std::string> makeSection(std::vector<std::string> data, | |
| 206 | const int linewidth = 72) { | ||
| 207 | 3 | std::vector<std::string> out; | |
| 208 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | out.reserve(data.size()); |
| 209 | |||
| 210 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
3 | std::string line = ""; |
| 211 | 3 | const int number_of_entries = data.size(); | |
| 212 |
2/2✓ Branch 0 taken 318 times.
✓ Branch 1 taken 3 times.
|
321 | for (auto i = 0; i < number_of_entries; ++i) { |
| 213 |
1/2✓ Branch 2 taken 318 times.
✗ Branch 3 not taken.
|
318 | std::string item = data[i]; |
| 214 |
2/2✓ Branch 0 taken 315 times.
✓ Branch 1 taken 3 times.
|
318 | if (i < number_of_entries - 1) |
| 215 |
1/2✓ Branch 1 taken 315 times.
✗ Branch 2 not taken.
|
315 | item += ","; |
| 216 | else | ||
| 217 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | item += ";"; |
| 218 | |||
| 219 | 318 | const int line_length = line.length() + item.length(); | |
| 220 |
2/2✓ Branch 0 taken 69 times.
✓ Branch 1 taken 249 times.
|
318 | if (line_length > linewidth) { |
| 221 |
1/2✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
|
69 | out.push_back(line); |
| 222 |
1/2✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
|
69 | line = ""; |
| 223 | } | ||
| 224 |
1/2✓ Branch 1 taken 318 times.
✗ Branch 2 not taken.
|
318 | line += item; |
| 225 | 318 | } | |
| 226 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | out.push_back(line); |
| 227 | 6 | return out; | |
| 228 | 3 | } | |
| 229 | |||
| 230 | /** | ||
| 231 | * \ingroup Geometry | ||
| 232 | * \brief Write the IGES header into the given file. | ||
| 233 | * | ||
| 234 | * \param file_name File name to write the header in. | ||
| 235 | */ | ||
| 236 | 1 | void writeIGSHeader(std::string file_name) { | |
| 237 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | std::vector<std::string> section(4); |
| 238 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | section[0] = ""; |
| 239 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | section[1] = "IGES obtained from Bembel."; |
| 240 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | section[2] = "See <http://www.bembel.eu>"; |
| 241 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | section[3] = ""; |
| 242 | |||
| 243 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | writeSection(file_name, section, 'S'); |
| 244 | 2 | return; | |
| 245 | 1 | } | |
| 246 | |||
| 247 | /** | ||
| 248 | * \brief Convert a double to a string with given precision. | ||
| 249 | * | ||
| 250 | * \param d double to be converted. | ||
| 251 | * \param precision Precision of the conversion. | ||
| 252 | */ | ||
| 253 | 262 | std::string double_to_string(double d, const int precision) { | |
| 254 |
1/2✓ Branch 1 taken 262 times.
✗ Branch 2 not taken.
|
262 | std::ostringstream stm; |
| 255 |
2/4✓ Branch 2 taken 262 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 262 times.
✗ Branch 6 not taken.
|
262 | stm << std::setprecision(precision) << d; |
| 256 |
1/2✓ Branch 1 taken 262 times.
✗ Branch 2 not taken.
|
524 | return stm.str(); |
| 257 | 262 | } | |
| 258 | |||
| 259 | /** * \ingroup Geometry | ||
| 260 | * \brief Write the IGES Global section into the given file. | ||
| 261 | * | ||
| 262 | * \param file_name File name to write the section in. | ||
| 263 | * \return Number of lines of this section. | ||
| 264 | */ | ||
| 265 | 1 | int writeGlobalSection(std::string file_name) { | |
| 266 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | std::vector<std::string> out(24); |
| 267 | 1 | std::time_t now = std::time(nullptr); | |
| 268 | |||
| 269 | 1 | std::tm* localTime = std::localtime(&now); | |
| 270 | char dateString[11]; // "YYYY-MM-DD\0" | ||
| 271 | 1 | std::strftime(dateString, sizeof(dateString), "%Y-%m-%d", localTime); | |
| 272 | // Parameter Deliminator Character | ||
| 273 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[0] = "1H,"; |
| 274 | // Record Delimiter Character | ||
| 275 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[1] = "1H;"; |
| 276 | // Product ID from Sender | ||
| 277 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[2] = "Bembel"; |
| 278 | // File Name | ||
| 279 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[3] = file_name; |
| 280 | // System ID | ||
| 281 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[4] = "Bembel"; |
| 282 | // Pre-processor Version | ||
| 283 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[5] = "writeIGSFile"; |
| 284 | // Number of Bits for Integers | ||
| 285 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[6] = "32"; |
| 286 | // Single Precision Magnitude | ||
| 287 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[7] = "75"; |
| 288 | // Single Precision Significance | ||
| 289 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[8] = "6"; |
| 290 | // Double Precision Magnitude | ||
| 291 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[9] = "75"; |
| 292 | // Double Precision Significance | ||
| 293 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[10] = "15"; |
| 294 | // Product ID for Receiver | ||
| 295 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[11] = "Nurbs from Bembel"; |
| 296 | // Model Space Scale | ||
| 297 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[12] = "1.0"; |
| 298 | // Unit Flag (6 = metres) | ||
| 299 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[13] = "6"; |
| 300 | // Units (metres = "M") | ||
| 301 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[14] = "M"; |
| 302 | // Maximum Number of Line Weights | ||
| 303 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[15] = "1000"; |
| 304 | // Size of Maximum Line Width | ||
| 305 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[16] = "1.0"; |
| 306 | // Date and Time of file generation | ||
| 307 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[17] = dateString; |
| 308 | // Minimum User-intended Resolution | ||
| 309 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[18] = "0.000001"; |
| 310 | // Approximate Maximum Coordinate | ||
| 311 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[19] = "10000.0"; |
| 312 | // Name of Author | ||
| 313 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[20] = "Maximilian Nolte"; |
| 314 | // Author's Organization | ||
| 315 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[21] = "CEM - TU Darmstadt"; |
| 316 | // IGES Version Number (3 = IGES version 2.0) | ||
| 317 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[22] = "3"; |
| 318 | // Drafting Standard Code (0 = no standard) | ||
| 319 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | out[23] = "0"; |
| 320 | |||
| 321 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | std::vector<std::string> section = makeSection(out); |
| 322 | |||
| 323 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | writeSection(file_name, section, 'G'); |
| 324 | 2 | return section.size(); | |
| 325 | 1 | } | |
| 326 | |||
| 327 | /** | ||
| 328 | * \ingroup Geometry | ||
| 329 | * \brief Write the IGES Directory section into the given file. | ||
| 330 | * | ||
| 331 | * \param file_name File name to write the section in. | ||
| 332 | * \param start_idx Vector containing the start lines of the sections. | ||
| 333 | * \param number_of_lines Vector containing the lengths of the sections. | ||
| 334 | * \return Number of lines of this section. | ||
| 335 | */ | ||
| 336 | 1 | int writeDirectory(std::string file_name, std::vector<int> start_idx, | |
| 337 | std::vector<int> number_of_lines) { | ||
| 338 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | assert(start_idx.size() == number_of_lines.size()); |
| 339 | |||
| 340 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | std::ofstream fid(file_name, std::ios::app); |
| 341 | 1 | int tot_number_of_lines = 0; | |
| 342 | 1 | const int number_of_patches = start_idx.size(); | |
| 343 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | for (auto i = 0; i < number_of_patches; ++i) { |
| 344 | fid << std::setw(8) << "128" | ||
| 345 |
3/6✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
|
2 | << std::setw(8) << start_idx[i] |
| 346 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | << std::setw(8) << 0 |
| 347 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | << std::setw(8) << 0 |
| 348 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | << std::setw(8) << 0 |
| 349 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | << std::setw(8) << 0 |
| 350 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | << std::setw(8) << 0 |
| 351 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | << std::setw(8) << 0 |
| 352 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | << std::setw(8) << 0 |
| 353 | << "D" | ||
| 354 |
5/10✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
|
2 | << std::setw(7) << (i + 1) * 2 - 1<< "\n"; |
| 355 | |||
| 356 | fid << std::setw(8) << "128" | ||
| 357 |
3/6✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
|
2 | << std::setw(8) << 0 |
| 358 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | << std::setw(8) << 0 |
| 359 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | << std::setw(8) << number_of_lines[i] |
| 360 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | << std::setw(8) << 0 |
| 361 | << std::setw(8) << " " | ||
| 362 | << std::setw(8) << " " | ||
| 363 | << std::setw(8) << " " | ||
| 364 |
8/16✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 2 times.
✗ Branch 16 not taken.
✓ Branch 19 taken 2 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 2 times.
✗ Branch 23 not taken.
✓ Branch 26 taken 2 times.
✗ Branch 27 not taken.
|
2 | << std::setw(8) << 0 |
| 365 | << "D" | ||
| 366 |
5/10✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 2 times.
✗ Branch 15 not taken.
|
2 | << std::setw(7) << (i + 1) * 2 << "\n"; |
| 367 | |||
| 368 | 2 | tot_number_of_lines += 2; | |
| 369 | } | ||
| 370 | 1 | return tot_number_of_lines; | |
| 371 | 1 | } | |
| 372 | |||
| 373 | /** | ||
| 374 | * \ingroup Geometry | ||
| 375 | * \brief This Function writes the patch from Bembel into a vector which can be | ||
| 376 | *written into an IGES file. | ||
| 377 | * | ||
| 378 | * This function assumes that the patch knot vectors do not contains internal | ||
| 379 | * nodes. | ||
| 380 | * | ||
| 381 | * \param patch Bembel patch containing all information | ||
| 382 | * \param precision Number of significant digits to save floats | ||
| 383 | * \return Vector with patch data in IGES format. | ||
| 384 | */ | ||
| 385 | 2 | std::vector<std::string> writePatchData(const Patch& patch, | |
| 386 | const int precision) { | ||
| 387 | 2 | const int degree_x = patch.polynomial_degree_x_; | |
| 388 | 2 | const int degree_y = patch.polynomial_degree_y_; | |
| 389 | |||
| 390 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | assert(patch.unique_knots_x_.size() == 2 && |
| 391 | "We can not handle internal knots"); | ||
| 392 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | assert(patch.unique_knots_y_.size() == 2 && |
| 393 | "We can not handle internal knots"); | ||
| 394 | |||
| 395 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | std::vector<double> knots_x(2 * degree_x, 0); |
| 396 |
2/2✓ Branch 1 taken 12 times.
✓ Branch 2 taken 2 times.
|
14 | for (auto i = 0; i <= degree_x; ++i) knots_x[degree_x + i] = 1; |
| 397 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | std::vector<double> knots_y(2 * degree_y, 0); |
| 398 |
2/2✓ Branch 1 taken 13 times.
✓ Branch 2 taken 2 times.
|
15 | for (auto i = 0; i <= degree_y; ++i) knots_y[degree_y + i] = 1; |
| 399 | |||
| 400 | 2 | const std::array<double, 2> span_x = {0, 1}; | |
| 401 | 2 | const std::array<double, 2> span_y = {0, 1}; | |
| 402 | |||
| 403 | 2 | const int number_of_points_x = knots_x.size() - degree_x; | |
| 404 | 2 | const int number_of_points_y = knots_y.size() - degree_y; | |
| 405 | |||
| 406 | 2 | const int size = patch.data_.size() / 4; | |
| 407 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | std::vector<double> weights(size); |
| 408 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | std::vector<double> coordinates_x(size); |
| 409 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | std::vector<double> coordinates_y(size); |
| 410 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | std::vector<double> coordinates_z(size); |
| 411 | // transform from wx, wy, wz to x, y, z | ||
| 412 | // further more switch row major and column major | ||
| 413 |
2/2✓ Branch 0 taken 55 times.
✓ Branch 1 taken 2 times.
|
57 | for (auto i = 0; i < size; ++i) { |
| 414 | 55 | const int rowIndex = i % number_of_points_y; | |
| 415 | 55 | const int colIndex = i / number_of_points_y; | |
| 416 | |||
| 417 | // Calculate the index for the corresponding element in row-major order | ||
| 418 | 55 | const int j = rowIndex * number_of_points_x + colIndex; | |
| 419 | |||
| 420 | 55 | double weight = patch.data_[i * 4 + 3]; | |
| 421 | 55 | weights[j] = weight; | |
| 422 | 55 | coordinates_x[j] = patch.data_[i * 4] / weight; | |
| 423 | 55 | coordinates_y[j] = patch.data_[i * 4 + 1] / weight; | |
| 424 | 55 | coordinates_z[j] = patch.data_[i * 4 + 2] / weight; | |
| 425 | } | ||
| 426 | |||
| 427 | 2 | const int number_of_data_entries = 16; | |
| 428 | const int size_data = | ||
| 429 | 2 | number_of_data_entries + 4 * size + knots_x.size() + knots_y.size(); | |
| 430 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | std::vector<std::string> patch_data(size_data); |
| 431 | |||
| 432 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | patch_data[0] = "128"; |
| 433 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | patch_data[1] = std::to_string(number_of_points_x - 1); |
| 434 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | patch_data[2] = std::to_string(number_of_points_y - 1); |
| 435 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | patch_data[3] = std::to_string(degree_x - 1); |
| 436 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | patch_data[4] = std::to_string(degree_y - 1); |
| 437 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | patch_data[5] = "0"; |
| 438 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | patch_data[6] = "0"; |
| 439 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | patch_data[7] = "0"; |
| 440 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | patch_data[8] = "0"; |
| 441 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | patch_data[9] = "0"; |
| 442 | |||
| 443 |
2/2✓ Branch 1 taken 20 times.
✓ Branch 2 taken 2 times.
|
22 | for (auto i = 0; i < knots_x.size(); ++i) { |
| 444 |
1/2✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
|
20 | patch_data[10 + i] = double_to_string(knots_x[i], precision); |
| 445 | } | ||
| 446 | |||
| 447 | 2 | const int idx_knots_y = 10 + knots_x.size(); | |
| 448 |
2/2✓ Branch 1 taken 22 times.
✓ Branch 2 taken 2 times.
|
24 | for (auto i = 0; i < knots_y.size(); ++i) { |
| 449 |
1/2✓ Branch 2 taken 22 times.
✗ Branch 3 not taken.
|
22 | patch_data[idx_knots_y + i] = double_to_string(knots_y[i], precision); |
| 450 | } | ||
| 451 | |||
| 452 | 2 | const int idx_weights = 10 + knots_x.size() + knots_y.size(); | |
| 453 |
2/2✓ Branch 0 taken 55 times.
✓ Branch 1 taken 2 times.
|
57 | for (auto i = 0; i < size; ++i) { |
| 454 |
1/2✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
|
55 | patch_data[idx_weights + i] = double_to_string(weights[i], precision); |
| 455 | |||
| 456 | 55 | patch_data[idx_weights + size + i * 3] = | |
| 457 |
1/2✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
|
110 | double_to_string(coordinates_x[i], precision); |
| 458 | 55 | patch_data[idx_weights + size + i * 3 + 1] = | |
| 459 |
1/2✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
|
110 | double_to_string(coordinates_y[i], precision); |
| 460 | 55 | patch_data[idx_weights + size + i * 3 + 2] = | |
| 461 |
1/2✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
|
110 | double_to_string(coordinates_z[i], precision); |
| 462 | } | ||
| 463 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | patch_data[idx_weights + 4 * size] = std::to_string(span_x[0]); |
| 464 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | patch_data[idx_weights + 4 * size + 1] = std::to_string(span_x[1]); |
| 465 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | patch_data[idx_weights + 4 * size + 2] = std::to_string(span_y[0]); |
| 466 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | patch_data[idx_weights + 4 * size + 3] = std::to_string(span_y[1]); |
| 467 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | patch_data[idx_weights + 4 * size + 4] = "0"; |
| 468 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | patch_data[idx_weights + 4 * size + 5] = "0"; |
| 469 | |||
| 470 | 4 | return patch_data; | |
| 471 | 2 | } | |
| 472 | |||
| 473 | /** | ||
| 474 | * \ingroup Geometry | ||
| 475 | * \brief Writes Geometry into an IGES file format. | ||
| 476 | * | ||
| 477 | * \param geometry PatchVector which is written to the file. | ||
| 478 | * \param file_name File name to write to. | ||
| 479 | * \param precision Significant number of digits for writing floats. | ||
| 480 | */ | ||
| 481 | 1 | void writeIGSFile(const std::vector<Patch>& geometry, std::string file_name, | |
| 482 | const int precision = 6) { | ||
| 483 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | std::ofstream out(file_name); |
| 484 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | out.close(); |
| 485 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | writeIGSHeader(file_name); |
| 486 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | const int size_global = writeGlobalSection(file_name); |
| 487 | |||
| 488 | 1 | const int number_of_patches = geometry.size(); | |
| 489 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | std::vector<int> start_idx(number_of_patches); |
| 490 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | std::vector<int> end_idx(number_of_patches); |
| 491 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | std::vector<std::vector<std::string>> patch_sections(number_of_patches); |
| 492 | 1 | int start_line = 1; | |
| 493 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | for (auto i = 0; i < number_of_patches; ++i) { |
| 494 | const std::vector<std::string> patch_data = | ||
| 495 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | writePatchData(geometry[i], precision); |
| 496 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | patch_sections[i] = makeSection(patch_data, 64); |
| 497 | |||
| 498 | 2 | start_idx[i] = start_line; | |
| 499 | 2 | start_line += patch_sections[i].size(); | |
| 500 | 2 | end_idx[i] = patch_sections[i].size(); | |
| 501 | 2 | } | |
| 502 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
|
1 | const int size_directory = writeDirectory(file_name, start_idx, end_idx); |
| 503 | |||
| 504 | 1 | int first_line = 1; | |
| 505 | 1 | int size_parameter = 0; | |
| 506 |
2/2✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 times.
|
3 | for (auto it = patch_sections.begin(); it != patch_sections.end(); ++it) { |
| 507 |
1/2✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | const int i = std::distance(patch_sections.begin(), it); |
| 508 | const int last_idx = | ||
| 509 |
2/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
|
2 | writeParameterSection(file_name, *it, 1 + 2 * i, first_line); |
| 510 | 2 | first_line = last_idx; | |
| 511 | 2 | size_parameter += (*it).size(); | |
| 512 | } | ||
| 513 | |||
| 514 | // Terminate Section | ||
| 515 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | std::stringstream last_section; |
| 516 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | last_section << std::setw(7) << 4 << "S" |
| 517 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
|
1 | << std::setw(7) << size_global << "G" |
| 518 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
|
1 | << std::setw(7) << size_directory << "D" |
| 519 |
5/10✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
|
1 | << std::setw(7) << size_parameter << "P"; |
| 520 | |||
| 521 | |||
| 522 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | std::ofstream file(file_name, std::ios::app); |
| 523 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | file << std::left << std::setw(72) << last_section.str() |
| 524 |
4/8✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
|
1 | << "T" |
| 525 |
4/8✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
|
1 | << std::right << std::setw(7) << 1 << "\n"; |
| 526 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | file.close(); |
| 527 | |||
| 528 | 2 | return; | |
| 529 | 1 | } | |
| 530 | } // namespace Bembel | ||
| 531 | #endif // BEMBEL_SRC_GEOMETRY_GEOMETRYIGS_HPP_ | ||
| 532 |