12 #ifndef BEMBEL_SRC_GEOMETRY_GEOMETRYIGS_HPP_
13 #define BEMBEL_SRC_GEOMETRY_GEOMETRYIGS_HPP_
27 std::vector<int> patch_lines;
30 std::cerr <<
"File " << file_name <<
" doesn't exist!";
37 std::cerr <<
"Format of the file not supported! I assume that character 72 "
38 "denotes the section";
42 while (row[72] !=
'D') {
44 assert(!file.eof() &&
"End of file should not be found here!");
48 while (row[72] !=
'P') {
49 std::stringstream iss;
51 std::vector<int> info1, info2;
54 info1.push_back(std::stoi(word));
56 assert(info1[0] == 128 &&
"Entry type must be NURBS surface!");
63 info2.push_back(std::stoi(word));
67 patch_lines.push_back(info2[3]);
68 assert(!file.eof() &&
"End of file should not be found here!");
72 std::vector<Patch> out;
73 out.reserve(patch_lines.size());
74 const int number_of_patches = patch_lines.size();
75 for (
auto i = 0; i < number_of_patches; ++i) {
76 std::stringstream iss;
78 std::vector<double> data;
79 for (
auto j = 0; j < patch_lines[i]; ++j) {
81 std::string raw_data = row.substr(0, 64);
82 raw_data.erase(std::remove(raw_data.begin(), raw_data.end(),
' '),
86 while (std::getline(iss, word,
',')) {
87 data.push_back(atof(word.c_str()));
94 const int K1 = data[1];
95 const int K2 = data[2];
96 const int M1 = data[3];
97 const int M2 = data[4];
99 const int N1 = 1 + K1 - M1;
100 const int N2 = 1 + K2 - M2;
101 const int A = N1 + 2 * M1;
102 const int B = N2 + 2 * M2;
103 const int C = (1 + K1) * (1 + K2);
106 data.erase(data.begin(), data.begin() + 10);
109 std::vector<double> tempknt1(data.begin(), data.begin() + A + 1);
110 std::vector<double> tempknt2(data.begin() + A + 1,
111 data.begin() + A + B + 2);
113 const int M = K2 + 1;
114 const int N = K1 + 1;
116 Eigen::MatrixXd weights(M, N);
117 auto it_weights = data.begin() + A + B + 2;
118 for (
auto entry = it_weights; entry != it_weights + C; ++entry) {
119 int index = entry - it_weights;
120 weights((
int)index / N, index % N) = *entry;
123 Eigen::MatrixXd x_coordinates(M, N);
124 Eigen::MatrixXd y_coordinates(M, N);
125 Eigen::MatrixXd z_coordinates(M, N);
126 auto it_points = data.begin() + A + B + C + 2;
127 for (
auto entry = it_points; entry != it_points + 3 * C; entry += 3) {
128 int index = (int)(entry - it_points) / 3;
129 x_coordinates((
int)index / N, index % N) = *entry;
130 y_coordinates((
int)index / N, index % N) = *(entry + 1);
131 z_coordinates((
int)index / N, index % N) = *(entry + 2);
135 x_coordinates = x_coordinates.cwiseProduct(weights);
136 y_coordinates = y_coordinates.cwiseProduct(weights);
137 z_coordinates = z_coordinates.cwiseProduct(weights);
139 std::vector<Eigen::MatrixXd> tmp = {x_coordinates, y_coordinates,
140 z_coordinates, weights};
143 tempPatch.
init_Patch(tmp, tempknt1, tempknt2);
144 out.push_back(tempPatch);
159 const std::vector<std::string>& section,
160 const char section_char) {
161 std::ofstream file(file_name, std::ios::app);
162 for (
auto it = section.begin(); it != section.end(); ++it) {
163 const int index = std::distance(section.begin(), it);
164 file << std::left << std::setw(72) << *it << section_char << std::right
165 << std::setw(7) << index + 1 <<
"\n";
182 const std::vector<std::string>& section,
183 const int patch_idx,
const int start_count) {
184 std::ofstream file(file_name, std::ios::app);
185 int last_line = start_count;
186 for (
auto it = section.begin(); it != section.end(); ++it) {
187 file << std::left << std::setw(64) << *it
188 << std::right << std::setw(8) << patch_idx <<
"P"
189 << std::right << std::setw(7) << last_line <<
"\n";
205 std::vector<std::string>
makeSection(std::vector<std::string> data,
206 const int linewidth = 72) {
207 std::vector<std::string> out;
208 out.reserve(data.size());
210 std::string line =
"";
211 const int number_of_entries = data.size();
212 for (
auto i = 0; i < number_of_entries; ++i) {
213 std::string item = data[i];
214 if (i < number_of_entries - 1)
219 const int line_length = line.length() + item.length();
220 if (line_length > linewidth) {
237 std::vector<std::string> section(4);
239 section[1] =
"IGES obtained from Bembel.";
240 section[2] =
"See <http://www.bembel.eu>";
254 std::ostringstream stm;
255 stm << std::setprecision(precision) << d;
266 std::vector<std::string> out(24);
267 std::time_t now = std::time(
nullptr);
269 std::tm* localTime = std::localtime(&now);
271 std::strftime(dateString,
sizeof(dateString),
"%Y-%m-%d", localTime);
283 out[5] =
"writeIGSFile";
295 out[11] =
"Nurbs from Bembel";
307 out[17] = dateString;
309 out[18] =
"0.000001";
313 out[20] =
"Maximilian Nolte";
315 out[21] =
"CEM - TU Darmstadt";
321 std::vector<std::string> section =
makeSection(out);
324 return section.size();
337 std::vector<int> number_of_lines) {
338 assert(start_idx.size() == number_of_lines.size());
340 std::ofstream fid(file_name, std::ios::app);
341 int tot_number_of_lines = 0;
342 const int number_of_patches = start_idx.size();
343 for (
auto i = 0; i < number_of_patches; ++i) {
344 fid << std::setw(8) <<
"128"
345 << std::setw(8) << start_idx[i]
354 << std::setw(7) << (i + 1) * 2 - 1<<
"\n";
356 fid << std::setw(8) <<
"128"
359 << std::setw(8) << number_of_lines[i]
361 << std::setw(8) <<
" "
362 << std::setw(8) <<
" "
363 << std::setw(8) <<
" "
366 << std::setw(7) << (i + 1) * 2 <<
"\n";
368 tot_number_of_lines += 2;
370 return tot_number_of_lines;
386 const int precision) {
387 const int degree_x = patch.polynomial_degree_x_;
388 const int degree_y = patch.polynomial_degree_y_;
390 assert(patch.unique_knots_x_.size() == 2 &&
391 "We can not handle internal knots");
392 assert(patch.unique_knots_y_.size() == 2 &&
393 "We can not handle internal knots");
395 std::vector<double> knots_x(2 * degree_x, 0);
396 for (
auto i = 0; i <= degree_x; ++i) knots_x[degree_x + i] = 1;
397 std::vector<double> knots_y(2 * degree_y, 0);
398 for (
auto i = 0; i <= degree_y; ++i) knots_y[degree_y + i] = 1;
400 const std::array<double, 2> span_x = {0, 1};
401 const std::array<double, 2> span_y = {0, 1};
403 const int number_of_points_x = knots_x.size() - degree_x;
404 const int number_of_points_y = knots_y.size() - degree_y;
406 const int size = patch.
data_.size() / 4;
407 std::vector<double> weights(size);
408 std::vector<double> coordinates_x(size);
409 std::vector<double> coordinates_y(size);
410 std::vector<double> coordinates_z(size);
413 for (
auto i = 0; i < size; ++i) {
414 const int rowIndex = i % number_of_points_y;
415 const int colIndex = i / number_of_points_y;
418 const int j = rowIndex * number_of_points_x + colIndex;
420 double weight = patch.
data_[i * 4 + 3];
422 coordinates_x[j] = patch.
data_[i * 4] / weight;
423 coordinates_y[j] = patch.
data_[i * 4 + 1] / weight;
424 coordinates_z[j] = patch.
data_[i * 4 + 2] / weight;
427 const int number_of_data_entries = 16;
428 const int size_data =
429 number_of_data_entries + 4 * size + knots_x.size() + knots_y.size();
430 std::vector<std::string> patch_data(size_data);
432 patch_data[0] =
"128";
433 patch_data[1] = std::to_string(number_of_points_x - 1);
434 patch_data[2] = std::to_string(number_of_points_y - 1);
435 patch_data[3] = std::to_string(degree_x - 1);
436 patch_data[4] = std::to_string(degree_y - 1);
443 for (
auto i = 0; i < knots_x.size(); ++i) {
447 const int idx_knots_y = 10 + knots_x.size();
448 for (
auto i = 0; i < knots_y.size(); ++i) {
452 const int idx_weights = 10 + knots_x.size() + knots_y.size();
453 for (
auto i = 0; i < size; ++i) {
456 patch_data[idx_weights + size + i * 3] =
458 patch_data[idx_weights + size + i * 3 + 1] =
460 patch_data[idx_weights + size + i * 3 + 2] =
463 patch_data[idx_weights + 4 * size] = std::to_string(span_x[0]);
464 patch_data[idx_weights + 4 * size + 1] = std::to_string(span_x[1]);
465 patch_data[idx_weights + 4 * size + 2] = std::to_string(span_y[0]);
466 patch_data[idx_weights + 4 * size + 3] = std::to_string(span_y[1]);
467 patch_data[idx_weights + 4 * size + 4] =
"0";
468 patch_data[idx_weights + 4 * size + 5] =
"0";
481 void writeIGSFile(
const std::vector<Patch>& geometry, std::string file_name,
482 const int precision = 6) {
483 std::ofstream out(file_name);
488 const int number_of_patches = geometry.size();
489 std::vector<int> start_idx(number_of_patches);
490 std::vector<int> end_idx(number_of_patches);
491 std::vector<std::vector<std::string>> patch_sections(number_of_patches);
493 for (
auto i = 0; i < number_of_patches; ++i) {
494 const std::vector<std::string> patch_data =
498 start_idx[i] = start_line;
499 start_line += patch_sections[i].size();
500 end_idx[i] = patch_sections[i].size();
502 const int size_directory =
writeDirectory(file_name, start_idx, end_idx);
505 int size_parameter = 0;
506 for (
auto it = patch_sections.begin(); it != patch_sections.end(); ++it) {
507 const int i = std::distance(patch_sections.begin(), it);
510 first_line = last_idx;
511 size_parameter += (*it).size();
515 std::stringstream last_section;
516 last_section << std::setw(7) << 4 <<
"S"
517 << std::setw(7) << size_global <<
"G"
518 << std::setw(7) << size_directory <<
"D"
519 << std::setw(7) << size_parameter <<
"P";
522 std::ofstream file(file_name, std::ios::app);
523 file << std::left << std::setw(72) << last_section.str()
525 << std::right << std::setw(7) << 1 <<
"\n";
void init_Patch(const std::vector< Eigen::Matrix< double, -1, -1 >> &xyzw, const std::vector< double > &x_knots, const std::vector< double > &y_knots)
init
std::vector< double > data_
getter
int writeDirectory(std::string file_name, std::vector< int > start_idx, std::vector< int > number_of_lines)
Write the IGES Directory section into the given file.
int writeParameterSection(std::string file_name, const std::vector< std::string > §ion, const int patch_idx, const int start_count)
This function writes a the parameter section of the IGES file.
void writeIGSHeader(std::string file_name)
Write the IGES header into the given file.
void writeSection(std::string file_name, const std::vector< std::string > §ion, const char section_char)
This function writes a given section to the specified file.
std::vector< Patch > LoadGeometryFileIGS(const std::string &file_name) noexcept
loads geometry from IGES file. Note that the direction of the normals must be consistent.
std::vector< std::string > makeSection(std::vector< std::string > data, const int linewidth=72)
Transform a vector of Data in a vector of lines with a specific length.
std::vector< std::string > writePatchData(const Patch &patch, const int precision)
This Function writes the patch from Bembel into a vector which can be written into an IGES file.
void writeIGSFile(const std::vector< Patch > &geometry, std::string file_name, const int precision=6)
Writes Geometry into an IGES file format.
int writeGlobalSection(std::string file_name)
Write the IGES Global section into the given file.
Routines for the evalutation of pointwise errors.
std::string double_to_string(double d, const int precision)
Convert a double to a string with given precision.