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 |