GCC Code Coverage Report


Directory: Bembel/src/
File: Bembel/src/Geometry/GeometryIGS.hpp
Date: 2024-03-19 14:38:05
Exec Total Coverage
Lines: 294 298 98.7%
Functions: 10 10 100.0%
Branches: 244 442 55.2%

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