00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025 #include "Definitions.h"
00026 #include "Iterator.h"
00027
00028 #include "MeshKernel.h"
00029 #include "MeshIO.h"
00030 #include "Builder.h"
00031
00032 #include <Base/Console.h>
00033 #include <Base/Exception.h>
00034 #include <Base/Reader.h>
00035 #include <Base/Writer.h>
00036 #include <Base/FileInfo.h>
00037 #include <Base/Sequencer.h>
00038 #include <Base/Stream.h>
00039 #include <zipios++/gzipoutputstream.h>
00040
00041 #include <math.h>
00042 #include <sstream>
00043 #include <iomanip>
00044 #include <boost/regex.hpp>
00045
00046
00047 using namespace MeshCore;
00048
00049 char *upper(char * string)
00050 {
00051 int i;
00052 int l;
00053
00054 if (string != NULL) {
00055 l = std::strlen(string);
00056 for (i=0; i<l; i++)
00057 string[i] = toupper(string[i]);
00058 }
00059
00060 return string;
00061 }
00062
00063 char *ltrim (char *psz)
00064 {
00065 int i, sl;
00066
00067 if (psz) {
00068 for (i = 0; (psz[i] == 0x20) || (psz[i] == 0x09); i++);
00069 sl = std::strlen (psz + i);
00070 memmove (psz, psz + i, sl);
00071 psz[sl] = 0;
00072 }
00073 return psz;
00074 }
00075
00076 std::string& upper(std::string& str)
00077 {
00078 for (std::string::iterator it = str.begin(); it != str.end(); ++it)
00079 *it = toupper(*it);
00080 return str;
00081 }
00082
00083 std::string& ltrim(std::string& str)
00084 {
00085 std::string::size_type pos=0;
00086 for (std::string::iterator it = str.begin(); it != str.end(); ++it) {
00087 if (*it != 0x20 && *it != 0x09)
00088 break;
00089 pos++;
00090 }
00091 if (pos > 0)
00092 str = str.substr(pos);
00093 return str;
00094 }
00095
00096 int numDigits(int number)
00097 {
00098 number = std::abs(number);
00099 int digits = 1;
00100 int step = 10;
00101 while (step <= number) {
00102 digits++;
00103 step *= 10;
00104 }
00105 return digits;
00106 }
00107
00108
00109 typedef struct _Vector
00110 {
00111 double x;
00112 double y;
00113 double z;
00114 } Vector, *VectorPtr;
00115
00116
00117 struct NODE {float x, y, z;};
00118 struct TRIA {int iV[3];};
00119 struct QUAD {int iV[4];};
00120
00121
00122 #define VMod(v) (sqrt((v).x*(v).x + (v).y*(v).y + (v).z*(v).z))
00123
00124
00125 #define VDot(v1, v2) ((v1).x*(v2).x + (v1).y*(v2).y + (v1).z*(v2).z)
00126
00127
00128 #define VNew(a, b, c, r) ((r).x = (a), (r).y = (b), (r).z = (c))
00129
00130 #define VAdd(v1, v2, r) ((r).x = (v1).x + (v2).x , \
00131 (r).y = (v1).y + (v2).y , \
00132 (r).z = (v1).z + (v2).z )
00133
00134 #define VSub(v1, v2, r) ((r).x = (v1).x - (v2).x , \
00135 (r).y = (v1).y - (v2).y , \
00136 (r).z = (v1).z - (v2).z )
00137
00138 #define VCross(v1, v2, r) ((r).x = (v1).y * (v2).z - (v1).z * (v2).y , \
00139 (r).y = (v1).z * (v2).x - (v1).x * (v2).z , \
00140 (r).z = (v1).x * (v2).y - (v1).y * (v2).x )
00141
00142 #define VScalarMul(v, d, r) ((r).x = (v).x * (d) , \
00143 (r).y = (v).y * (d) , \
00144 (r).z = (v).z * (d) )
00145
00146 #define VUnit(v, t, r) ((t) = 1 / VMod(v) , \
00147 VScalarMul(v, t, r) )
00148
00149 typedef struct _Quaternion {
00150 Vector vect_part;
00151 double real_part;
00152 } Quaternion;
00153
00154 Quaternion
00155 Build_Rotate_Quaternion(Vector axis, double cos_angle)
00156 {
00157 Quaternion quat;
00158 double sin_half_angle;
00159 double cos_half_angle;
00160 double angle;
00161
00162
00163 if ( cos_angle > 1.0 ) cos_angle = 1.0;
00164 if ( cos_angle < -1.0 ) cos_angle = -1.0;
00165 angle = acos(cos_angle);
00166 sin_half_angle = sin(angle / 2);
00167 cos_half_angle = cos(angle / 2);
00168
00169 VScalarMul(axis, sin_half_angle, quat.vect_part);
00170 quat.real_part = cos_half_angle;
00171
00172 return quat;
00173 }
00174
00175 static Quaternion
00176 QQMul(Quaternion *q1, Quaternion *q2)
00177 {
00178 Quaternion res;
00179 Vector temp_v;
00180
00181 res.real_part = q1->real_part * q2->real_part -
00182 VDot(q1->vect_part, q2->vect_part);
00183 VCross(q1->vect_part, q2->vect_part, res.vect_part);
00184 VScalarMul(q1->vect_part, q2->real_part, temp_v);
00185 VAdd(temp_v, res.vect_part, res.vect_part);
00186 VScalarMul(q2->vect_part, q1->real_part, temp_v);
00187 VAdd(temp_v, res.vect_part, res.vect_part);
00188
00189 return res;
00190 }
00191
00192 static void
00193 Quaternion_To_Axis_Angle(Quaternion *q, Vector *axis, double *angle)
00194 {
00195 double half_angle;
00196 double sin_half_angle;
00197
00198 half_angle = acos(q->real_part);
00199 sin_half_angle = sin(half_angle);
00200 *angle = half_angle * 2;
00201 if ( sin_half_angle < 1e-8 && sin_half_angle > -1e-8 )
00202 VNew(1, 0, 0, *axis);
00203 else
00204 {
00205 sin_half_angle = 1 / sin_half_angle;
00206 VScalarMul(q->vect_part, sin_half_angle, *axis);
00207 }
00208 }
00209
00210 static void
00211 Convert_Camera_Model(Vector *pos, Vector *at, Vector *up, Vector *res_axis,
00212 double *res_angle)
00213 {
00214 Vector n, v;
00215
00216 Quaternion rot_quat;
00217 Vector norm_axis;
00218 Quaternion norm_quat;
00219 Quaternion inv_norm_quat;
00220 Quaternion y_quat, new_y_quat, rot_y_quat;
00221 Vector new_y;
00222
00223 double temp_d;
00224 Vector temp_v;
00225
00226
00227 VSub(*at, *pos, n);
00228 VUnit(n, temp_d, n);
00229
00230
00231 VUnit(*up, temp_d, *up);
00232 temp_d = VDot(*up, n);
00233 VScalarMul(n, temp_d, temp_v);
00234 VSub(*up, temp_v, v);
00235 VUnit(v, temp_d, v);
00236
00237 VNew(n.y, -n.x, 0, norm_axis);
00238 if ( VDot(norm_axis, norm_axis) < 1e-8 )
00239 {
00240
00241 if ( n.z > 0.0 )
00242 {
00243 norm_quat.real_part = 0.0;
00244 VNew(0, 1, 0, norm_quat.vect_part);
00245 }
00246 else
00247 {
00248 norm_quat.real_part = 1.0;
00249 VNew(0, 0, 0, norm_quat.vect_part);
00250 }
00251 }
00252 else
00253 {
00254 VUnit(norm_axis, temp_d, norm_axis);
00255 norm_quat = Build_Rotate_Quaternion(norm_axis, -n.z);
00256 }
00257
00258
00259
00260
00261
00262
00263
00264 inv_norm_quat.real_part = norm_quat.real_part;
00265 VScalarMul(norm_quat.vect_part, -1, inv_norm_quat.vect_part);
00266
00267
00268 y_quat.real_part = 0.0;
00269 VNew(0, 1, 0, y_quat.vect_part);
00270 new_y_quat = QQMul(&norm_quat, &y_quat);
00271 new_y_quat = QQMul(&new_y_quat, &inv_norm_quat);
00272 new_y = new_y_quat.vect_part;
00273
00274
00275 VCross(new_y, v, temp_v);
00276 if ( VDot(temp_v, temp_v) < 1.e-8 )
00277 {
00278
00279
00280
00281 VNew(0, -v.z, v.y, temp_v);
00282 if ( VDot(temp_v, temp_v) < 1.e-8 )
00283 VNew(v.z, 0, -v.x, temp_v);
00284 }
00285 VUnit(temp_v, temp_d, temp_v);
00286 rot_y_quat = Build_Rotate_Quaternion(temp_v, VDot(new_y, v));
00287
00288
00289
00290
00291
00292
00293 rot_quat = QQMul(&rot_y_quat, &norm_quat);
00294
00295
00296 Quaternion_To_Axis_Angle(&rot_quat, res_axis, res_angle);
00297 }
00298
00299
00300
00301 bool MeshInput::LoadAny(const char* FileName)
00302 {
00303
00304 Base::FileInfo fi(FileName);
00305 if (!fi.exists() || !fi.isFile())
00306 throw Base::FileException("File does not exist",FileName);
00307 if (!fi.isReadable())
00308 throw Base::FileException("No permission on the file",FileName);
00309
00310 Base::ifstream str(fi, std::ios::in | std::ios::binary);
00311
00312 if (fi.hasExtension("bms")) {
00313 _rclMesh.Read(str);
00314 return true;
00315 }
00316 else {
00317
00318 bool ok = false;
00319 if (fi.hasExtension("stl") || fi.hasExtension("ast")) {
00320 ok = LoadSTL(str);
00321 }
00322 else if (fi.hasExtension("iv")) {
00323 ok = LoadInventor( str );
00324 if (ok && _rclMesh.CountFacets() == 0)
00325 Base::Console().Warning("No usable mesh found in file '%s'", FileName);
00326 }
00327 else if (fi.hasExtension("nas") || fi.hasExtension("bdf")) {
00328 ok = LoadNastran( str );
00329 }
00330 else if (fi.hasExtension("obj")) {
00331 ok = LoadOBJ( str );
00332 }
00333 else if (fi.hasExtension("ply")) {
00334 ok = LoadPLY( str );
00335 }
00336 else {
00337 throw Base::FileException("File extension not supported",FileName);
00338 }
00339
00340 return ok;
00341 }
00342 }
00343
00347 bool MeshInput::LoadSTL (std::istream &rstrIn)
00348 {
00349 char szBuf[200];
00350
00351 if (!rstrIn || rstrIn.bad() == true)
00352 return false;
00353
00354
00355
00356
00357
00358
00359 std::streambuf* buf = rstrIn.rdbuf();
00360 if (!buf) return false;
00361 buf->pubseekoff(80, std::ios::beg, std::ios::in);
00362 uint32_t ulCt, ulBytes=50;
00363 rstrIn.read((char*)&ulCt, sizeof(ulCt));
00364
00365 if (ulCt > 1)
00366 ulBytes = 100;
00367
00368 if (rstrIn.read(szBuf, ulBytes) == false)
00369 return (ulCt==0);
00370 szBuf[ulBytes] = 0;
00371 upper(szBuf);
00372
00373 try {
00374 if ((strstr(szBuf, "SOLID") == NULL) && (strstr(szBuf, "FACET") == NULL) && (strstr(szBuf, "NORMAL") == NULL) &&
00375 (strstr(szBuf, "VERTEX") == NULL) && (strstr(szBuf, "ENDFACET") == NULL) && (strstr(szBuf, "ENDLOOP") == NULL)) {
00376
00377 buf->pubseekoff(0, std::ios::beg, std::ios::in);
00378 return LoadBinarySTL(rstrIn);
00379 }
00380 else {
00381
00382 buf->pubseekoff(0, std::ios::beg, std::ios::in);
00383 return LoadAsciiSTL(rstrIn);
00384 }
00385 }
00386 catch (const Base::MemoryException&) {
00387 _rclMesh.Clear();
00388 throw;
00389 }
00390 catch (const Base::AbortException&) {
00391 _rclMesh.Clear();
00392 return false;
00393 }
00394 catch (const Base::Exception&) {
00395 _rclMesh.Clear();
00396 throw;
00397 }
00398 catch (...) {
00399 _rclMesh.Clear();
00400 throw;
00401 }
00402
00403 return true;
00404 }
00405
00407 bool MeshInput::LoadOBJ (std::istream &rstrIn)
00408 {
00409 boost::regex rx_p("^v\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
00410 "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
00411 "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)\\s*$");
00412 boost::regex rx_f3("^f\\s+([0-9]+)/?[0-9]*/?[0-9]*"
00413 "\\s+([0-9]+)/?[0-9]*/?[0-9]*"
00414 "\\s+([0-9]+)/?[0-9]*/?[0-9]*\\s*$");
00415 boost::regex rx_f4("^f\\s+([0-9]+)/?[0-9]*/?[0-9]*"
00416 "\\s+([0-9]+)/?[0-9]*/?[0-9]*"
00417 "\\s+([0-9]+)/?[0-9]*/?[0-9]*"
00418 "\\s+([0-9]+)/?[0-9]*/?[0-9]*\\s*$");
00419 boost::cmatch what;
00420
00421 unsigned long segment=0;
00422 MeshPointArray meshPoints;
00423 MeshFacetArray meshFacets;
00424
00425 std::string line;
00426 float fX, fY, fZ;
00427 unsigned int i1=1,i2=1,i3=1,i4=1;
00428 MeshGeomFacet clFacet;
00429 MeshFacet item;
00430
00431 if (!rstrIn || rstrIn.bad() == true)
00432 return false;
00433
00434 std::streambuf* buf = rstrIn.rdbuf();
00435 if (!buf)
00436 return false;
00437
00438 bool readvertices=false;
00439 while (std::getline(rstrIn, line)) {
00440 for (std::string::iterator it = line.begin(); it != line.end(); ++it)
00441 *it = tolower(*it);
00442 if (boost::regex_match(line.c_str(), what, rx_p)) {
00443 readvertices = true;
00444 fX = (float)std::atof(what[1].first);
00445 fY = (float)std::atof(what[4].first);
00446 fZ = (float)std::atof(what[7].first);
00447 meshPoints.push_back(MeshPoint(Base::Vector3f(fX, fY, fZ)));
00448 }
00449 else if (boost::regex_match(line.c_str(), what, rx_f3)) {
00450
00451 if (readvertices) {
00452 readvertices = false;
00453 segment++;
00454 }
00455
00456
00457 i1 = std::atoi(what[1].first);
00458 i2 = std::atoi(what[2].first);
00459 i3 = std::atoi(what[3].first);
00460 item.SetVertices(i1-1,i2-1,i3-1);
00461 item.SetProperty(segment);
00462 meshFacets.push_back(item);
00463 }
00464 else if (boost::regex_match(line.c_str(), what, rx_f4)) {
00465
00466 if (readvertices) {
00467 readvertices = false;
00468 segment++;
00469 }
00470
00471
00472 i1 = std::atoi(what[1].first);
00473 i2 = std::atoi(what[2].first);
00474 i3 = std::atoi(what[3].first);
00475 i4 = std::atoi(what[4].first);
00476
00477 item.SetVertices(i1-1,i2-1,i3-1);
00478 item.SetProperty(segment);
00479 meshFacets.push_back(item);
00480
00481 item.SetVertices(i3-1,i4-1,i1-1);
00482 item.SetProperty(segment);
00483 meshFacets.push_back(item);
00484 }
00485 }
00486
00487 this->_rclMesh.Clear();
00488
00489
00490 unsigned long ct = meshPoints.size();
00491 std::list<unsigned long> removeFaces;
00492 for (MeshFacetArray::_TConstIterator it = meshFacets.begin(); it != meshFacets.end(); ++it) {
00493 bool ok = true;
00494 for (int i=0;i<3;i++) {
00495 if (it->_aulPoints[i] >= ct) {
00496 Base::Console().Warning("Face index %ld out of range\n", it->_aulPoints[i]);
00497 ok = false;
00498 }
00499 }
00500
00501 if (!ok)
00502 removeFaces.push_front(it-meshFacets.begin());
00503 }
00504
00505 for (std::list<unsigned long>::iterator it = removeFaces.begin(); it != removeFaces.end(); ++it)
00506 meshFacets.erase(meshFacets.begin() + *it);
00507
00508 MeshKernel tmp;
00509 tmp.Adopt(meshPoints,meshFacets);
00510 this->_rclMesh.Merge(tmp);
00511
00512 return true;
00513 }
00514
00515 bool MeshInput::LoadPLY (std::istream &inp)
00516 {
00517
00518 std::size_t v_count=0, f_count=0;
00519 MeshPointArray meshPoints;
00520 MeshFacetArray meshFacets;
00521
00522 enum {
00523 ascii, binary_little_endian, binary_big_endian
00524 } format;
00525 if (!inp || inp.bad() == true)
00526 return false;
00527
00528 std::streambuf* buf = inp.rdbuf();
00529 if (!buf)
00530 return false;
00531
00532
00533 char ply[3];
00534 inp.read(ply, 3);
00535 inp.ignore(1);
00536 if (!inp)
00537 return false;
00538 if ((ply[0] != 'p') || (ply[1] != 'l') || (ply[2] != 'y'))
00539 return false;
00540
00541 std::string line, element;
00542 bool xyz_float=false,xyz_double=false,rgb_value=false;
00543 while (std::getline(inp, line)) {
00544 std::istringstream str(line);
00545 str.unsetf(std::ios_base::skipws);
00546 str >> std::ws;
00547 if (str.eof())
00548 continue;
00549 std::string kw;
00550 str >> kw;
00551 if (kw == "format") {
00552 std::string format_string, version;
00553 char space_format_string, space_format_version;
00554 str >> space_format_string >> std::ws
00555 >> format_string >> space_format_version
00556 >> std::ws >> version >> std::ws;
00557 if (!str || !str.eof() ||
00558 !std::isspace(space_format_string) ||
00559 !std::isspace(space_format_version)) {
00560 return false;
00561 }
00562 if (format_string == "ascii") {
00563 format = ascii;
00564 }
00565 else if (format_string == "binary_big_endian") {
00566 format = binary_big_endian;
00567 }
00568 else if (format_string == "binary_little_endian") {
00569 format = binary_little_endian;
00570 }
00571 else {
00572
00573 return false;
00574 }
00575 if (version != "1.0") {
00576
00577 return false;
00578 }
00579 }
00580 else if (kw == "element") {
00581 std::string name;
00582 std::size_t count;
00583 char space_element_name, space_name_count;
00584 str >> space_element_name >> std::ws
00585 >> name >> space_name_count >> std::ws
00586 >> count >> std::ws;
00587 if (!str || !str.eof() ||
00588 !std::isspace(space_element_name) ||
00589 !std::isspace(space_name_count)) {
00590 return false;
00591 }
00592 else if (name == "vertex") {
00593 element = name;
00594 v_count = count;
00595 meshPoints.reserve(count);
00596 }
00597 else if (name == "face") {
00598 element = name;
00599 f_count = count;
00600 meshFacets.reserve(count);
00601 }
00602 else {
00603 element.clear();
00604 }
00605 }
00606 else if (kw == "property") {
00607 std::string type, name;
00608 char space;
00609 if (element == "vertex") {
00610 str >> space >> std::ws
00611 >> type >> space >> std::ws >> name >> std::ws;
00612 if (name == "x") {
00613 if (type == "float" || type == "float32")
00614 xyz_float = true;
00615 else if (type == "double" || type == "float64")
00616 xyz_double = true;
00617 }
00618 else if (name == "red") {
00619 rgb_value = true;
00620 }
00621 }
00622 else if (element == "face") {
00623 }
00624 }
00625 else if (kw == "end_header") {
00626 break;
00627 }
00628 }
00629
00630 if (format == ascii) {
00631 boost::regex rx_p("^([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
00632 "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
00633 "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)\\s*$");
00634 boost::regex rx_f("^\\s*3\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s*$");
00635 boost::cmatch what;
00636 Base::Vector3f pt;
00637 for (std::size_t i = 0; i < v_count && std::getline(inp, line); i++) {
00638 if (boost::regex_match(line.c_str(), what, rx_p)) {
00639 pt.x = (float)std::atof(what[1].first);
00640 pt.y = (float)std::atof(what[4].first);
00641 pt.z = (float)std::atof(what[7].first);
00642 meshPoints.push_back(pt);
00643 }
00644 else {
00645 return false;
00646 }
00647 }
00648 int f1, f2, f3;
00649 for (std::size_t i = 0; i < f_count && std::getline(inp, line); i++) {
00650 if (boost::regex_match(line.c_str(), what, rx_f)) {
00651 f1 = std::atoi(what[1].first);
00652 f2 = std::atoi(what[2].first);
00653 f3 = std::atoi(what[3].first);
00654 meshFacets.push_back(MeshFacet(f1,f2,f3));
00655 }
00656 }
00657 }
00658 else {
00659 Base::InputStream is(inp);
00660 if (format == binary_little_endian)
00661 is.setByteOrder(Base::Stream::LittleEndian);
00662 else
00663 is.setByteOrder(Base::Stream::BigEndian);
00664 int r,g,b;
00665 if (xyz_float) {
00666 Base::Vector3f pt;
00667 for (std::size_t i = 0; i < v_count; i++) {
00668 is >> pt.x >> pt.y >> pt.z;
00669 meshPoints.push_back(pt);
00670 if (rgb_value)
00671 is >> r >> g >> b;
00672 }
00673 }
00674 else if (xyz_double) {
00675 Base::Vector3d pt;
00676 for (std::size_t i = 0; i < v_count; i++) {
00677 is >> pt.x >> pt.y >> pt.z;
00678 is >> r >> g >> b;
00679 meshPoints.push_back(Base::Vector3f((float)pt.x,(float)pt.y,(float)pt.z));
00680 }
00681 }
00682 unsigned char n;
00683 int f1, f2, f3;
00684 for (std::size_t i = 0; i < f_count; i++) {
00685 is >> n;
00686 if (n==3) {
00687 is >> f1 >> f2 >> f3;
00688 meshFacets.push_back(MeshFacet(f1,f2,f3));
00689 }
00690 }
00691 }
00692
00693 this->_rclMesh.Clear();
00694
00695
00696 MeshKernel tmp;
00697 tmp.Adopt(meshPoints,meshFacets);
00698 this->_rclMesh.Merge(tmp);
00699
00700 return true;
00701 }
00702
00703 bool MeshInput::LoadMeshNode (std::istream &rstrIn)
00704 {
00705 boost::regex rx_p("^v\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
00706 "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
00707 "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)\\s*$");
00708 boost::regex rx_f("^f\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s*$");
00709 boost::regex rx_e("\\s*]\\s*");
00710 boost::cmatch what;
00711
00712 MeshPointArray meshPoints;
00713 MeshFacetArray meshFacets;
00714
00715 std::string line;
00716 float fX, fY, fZ;
00717 unsigned int i1=1,i2=1,i3=1;
00718 MeshGeomFacet clFacet;
00719
00720 if (!rstrIn || rstrIn.bad() == true)
00721 return false;
00722
00723 std::streambuf* buf = rstrIn.rdbuf();
00724 if (!buf)
00725 return false;
00726
00727 while (std::getline(rstrIn, line)) {
00728 for (std::string::iterator it = line.begin(); it != line.end(); ++it)
00729 *it = tolower(*it);
00730 if (boost::regex_match(line.c_str(), what, rx_p)) {
00731 fX = (float)std::atof(what[1].first);
00732 fY = (float)std::atof(what[4].first);
00733 fZ = (float)std::atof(what[7].first);
00734 meshPoints.push_back(MeshPoint(Base::Vector3f(fX, fY, fZ)));
00735 }
00736 else if (boost::regex_match(line.c_str(), what, rx_f)) {
00737 i1 = std::atoi(what[1].first);
00738 i2 = std::atoi(what[2].first);
00739 i3 = std::atoi(what[3].first);
00740 meshFacets.push_back(MeshFacet(i1-1,i2-1,i3-1));
00741 }
00742 else if (boost::regex_match(line.c_str(), what, rx_e)) {
00743 break;
00744 }
00745 }
00746
00747 this->_rclMesh.Clear();
00748
00749
00750 MeshKernel tmp;
00751 tmp.Adopt(meshPoints,meshFacets);
00752 this->_rclMesh.Merge(tmp);
00753
00754 return true;
00755 }
00756
00758 bool MeshInput::LoadAsciiSTL (std::istream &rstrIn)
00759 {
00760 boost::regex rx_p("^\\s*VERTEX\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
00761 "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
00762 "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)\\s*$");
00763 boost::regex rx_f("^\\s*FACET\\s+NORMAL\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
00764 "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
00765 "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)\\s*$");
00766 boost::cmatch what;
00767
00768 std::string line;
00769 float fX, fY, fZ;
00770 unsigned long ulVertexCt, ulFacetCt=0;
00771 MeshGeomFacet clFacet;
00772
00773 if (!rstrIn || rstrIn.bad() == true)
00774 return false;
00775
00776 std::streamoff ulSize = 0;
00777 std::streambuf* buf = rstrIn.rdbuf();
00778 ulSize = buf->pubseekoff(0, std::ios::end, std::ios::in);
00779 buf->pubseekoff(0, std::ios::beg, std::ios::in);
00780 ulSize -= 20;
00781
00782
00783 while (std::getline(rstrIn, line)) {
00784 for (std::string::iterator it = line.begin(); it != line.end(); ++it)
00785 *it = toupper(*it);
00786 if (line.find("ENDFACET") != std::string::npos)
00787 ulFacetCt++;
00788
00789 else if (rstrIn.tellg() > ulSize)
00790 break;
00791 else if (line.find("ENDSOLID") != std::string::npos)
00792 break;
00793 }
00794
00795
00796 buf->pubseekoff(0, std::ios::beg, std::ios::in);
00797
00798 MeshBuilder builder(this->_rclMesh);
00799 builder.Initialize(ulFacetCt);
00800
00801 ulVertexCt = 0;
00802 while (std::getline(rstrIn, line)) {
00803 for (std::string::iterator it = line.begin(); it != line.end(); ++it)
00804 *it = toupper(*it);
00805 if (boost::regex_match(line.c_str(), what, rx_f)) {
00806 fX = (float)std::atof(what[1].first);
00807 fY = (float)std::atof(what[4].first);
00808 fZ = (float)std::atof(what[7].first);
00809 clFacet.SetNormal(Base::Vector3f(fX, fY, fZ));
00810 }
00811 else if (boost::regex_match(line.c_str(), what, rx_p)) {
00812 fX = (float)std::atof(what[1].first);
00813 fY = (float)std::atof(what[4].first);
00814 fZ = (float)std::atof(what[7].first);
00815 clFacet._aclPoints[ulVertexCt++].Set(fX, fY, fZ);
00816 if (ulVertexCt == 3) {
00817 ulVertexCt = 0;
00818 builder.AddFacet(clFacet);
00819 }
00820 }
00821 }
00822
00823 builder.Finish();
00824
00825 return true;
00826 }
00827
00829 bool MeshInput::LoadBinarySTL (std::istream &rstrIn)
00830 {
00831 char szInfo[80];
00832 Base::Vector3f clVects[4];
00833 uint16_t usAtt;
00834 uint32_t ulCt;
00835
00836 if (!rstrIn || rstrIn.bad() == true)
00837 return false;
00838
00839
00840 rstrIn.read(szInfo, sizeof(szInfo));
00841
00842
00843 rstrIn.read((char*)&ulCt, sizeof(ulCt));
00844 if (rstrIn.bad() == true)
00845 return false;
00846
00847
00848 std::streamoff ulSize = 0;
00849 std::streambuf* buf = rstrIn.rdbuf();
00850 if (buf) {
00851 std::streamoff ulCurr;
00852 ulCurr = buf->pubseekoff(0, std::ios::cur, std::ios::in);
00853 ulSize = buf->pubseekoff(0, std::ios::end, std::ios::in);
00854 buf->pubseekoff(ulCurr, std::ios::beg, std::ios::in);
00855 }
00856
00857 uint32_t ulFac = (ulSize - (80 + sizeof(uint32_t))) / 50;
00858
00859
00860 if (ulCt > ulFac)
00861 return false;
00862
00863 MeshBuilder builder(this->_rclMesh);
00864 builder.Initialize(ulCt);
00865
00866 for (uint32_t i = 0; i < ulCt; i++) {
00867
00868 rstrIn.read((char*)&clVects, sizeof(clVects));
00869
00870 std::swap(clVects[0], clVects[3]);
00871 builder.AddFacet(clVects);
00872
00873
00874 rstrIn.read((char*)&usAtt, sizeof(usAtt));
00875 }
00876
00877 builder.Finish();
00878
00879 return true;
00880 }
00881
00883 void MeshInput::LoadXML (Base::XMLReader &reader)
00884 {
00885 MeshPointArray cPoints;
00886 MeshFacetArray cFacets;
00887
00888
00889
00890 reader.readElement("Points");
00891 int Cnt = reader.getAttributeAsInteger("Count");
00892
00893 cPoints.resize(Cnt);
00894 for (int i=0 ;i<Cnt ;i++) {
00895 reader.readElement("P");
00896 cPoints[i].x = (float)reader.getAttributeAsFloat("x");
00897 cPoints[i].y = (float)reader.getAttributeAsFloat("y");
00898 cPoints[i].z = (float)reader.getAttributeAsFloat("z");
00899 }
00900 reader.readEndElement("Points");
00901
00902 reader.readElement("Faces");
00903 Cnt = reader.getAttributeAsInteger("Count");
00904
00905 cFacets.resize(Cnt);
00906 for (int i=0 ;i<Cnt ;i++) {
00907 reader.readElement("F");
00908 cFacets[i]._aulPoints[0] = reader.getAttributeAsInteger("p0");
00909 cFacets[i]._aulPoints[1] = reader.getAttributeAsInteger("p1");
00910 cFacets[i]._aulPoints[2] = reader.getAttributeAsInteger("p2");
00911 cFacets[i]._aulNeighbours[0] = reader.getAttributeAsInteger("n0");
00912 cFacets[i]._aulNeighbours[1] = reader.getAttributeAsInteger("n1");
00913 cFacets[i]._aulNeighbours[2] = reader.getAttributeAsInteger("n2");
00914 }
00915
00916 reader.readEndElement("Faces");
00917 reader.readEndElement("Mesh");
00918
00919 _rclMesh.Adopt(cPoints, cFacets);
00920 }
00921
00923 bool MeshInput::LoadInventor (std::istream &rstrIn)
00924 {
00925 if (!rstrIn || rstrIn.bad() == true)
00926 return false;
00927
00928 boost::regex rx_p("\\s*([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
00929 "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
00930 "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
00931 "\\s*[\\,\\]]\\s*");
00932 boost::regex rx_f("\\s*([0-9]+)\\s*\\,\\s*"
00933 "\\s+([0-9]+)\\s*\\,\\s*"
00934 "\\s+([0-9]+)\\s*\\,\\s*");
00935 boost::cmatch what;
00936
00937
00938 std::streamoff ulSize = 0;
00939 std::streambuf* buf = rstrIn.rdbuf();
00940 if (!buf)
00941 return false;
00942 if (buf) {
00943 std::streamoff ulCurr;
00944 ulCurr = buf->pubseekoff(0, std::ios::cur, std::ios::in);
00945 ulSize = buf->pubseekoff(0, std::ios::end, std::ios::in);
00946 buf->pubseekoff(ulCurr, std::ios::beg, std::ios::in);
00947 }
00948
00949 std::string line;
00950 MeshGeomFacet clFacet;
00951 std::vector<MeshGeomFacet> clFacetAry;
00952 std::vector<Base::Vector3f> aclPoints;
00953
00954
00955 Base::SequencerLauncher seq("Loading...", ulSize/30);
00956 bool flag = false;
00957 bool normals = false;
00958 bool points = false;
00959 bool facets = false;
00960 while (std::getline(rstrIn, line) && !facets) {
00961 for (std::string::iterator it = line.begin(); it != line.end(); ++it)
00962 *it = toupper(*it);
00963
00964
00965 if (!normals && line.find("NORMAL {") != std::string::npos) {
00966 float fX, fY, fZ;
00967 normals = true;
00968 flag = true;
00969
00970
00971
00972
00973 std::getline(rstrIn, line);
00974 for (std::string::iterator it = line.begin(); it != line.end(); ++it)
00975 *it = toupper(*it);
00976 std::string::size_type pos = line.find("VECTOR [");
00977 if (pos != std::string::npos)
00978 line = line.substr(pos+8);
00979 do {
00980 if (boost::regex_match(line.c_str(), what, rx_p)) {
00981 fX = (float)std::atof(what[1].first);
00982 fY = (float)std::atof(what[4].first);
00983 fZ = (float)std::atof(what[7].first);
00984 clFacet.SetNormal(Base::Vector3f(fX, fY, fZ));
00985 clFacetAry.push_back(clFacet);
00986 seq.next(true);
00987 } else
00988 flag = false;
00989 } while (std::getline(rstrIn, line) && flag);
00990 }
00991
00992 else if (!points && line.find("COORDINATE3 {") != std::string::npos) {
00993 Base::Vector3f clPoint;
00994 points = true;
00995 flag = true;
00996
00997
00998
00999
01000 std::getline(rstrIn, line);
01001 for (std::string::iterator it = line.begin(); it != line.end(); ++it)
01002 *it = toupper(*it);
01003 std::string::size_type pos = line.find("POINT [");
01004 if (pos != std::string::npos)
01005 line = line.substr(pos+7);
01006 do {
01007 if (boost::regex_match(line.c_str(), what, rx_p)) {
01008 clPoint.x = (float)std::atof(what[1].first);
01009 clPoint.y = (float)std::atof(what[4].first);
01010 clPoint.z = (float)std::atof(what[7].first);
01011 aclPoints.push_back(clPoint);
01012 seq.next(true);
01013 } else
01014 flag = false;
01015 } while (std::getline(rstrIn, line) && flag);
01016 }
01017
01018 else if (points && line.find("INDEXEDFACESET {") != std::string::npos) {
01019 unsigned long ulPoints[3];
01020 facets = true;
01021 flag = true;
01022 unsigned long ulCt = 0;
01023
01024
01025
01026
01027
01028
01029 std::getline(rstrIn, line);
01030 for (std::string::iterator it = line.begin(); it != line.end(); ++it)
01031 *it = toupper(*it);
01032 std::string::size_type pos = line.find("COORDINDEX [");
01033 if (pos != std::string::npos)
01034 line = line.substr(pos+12);
01035 do {
01036 flag = false;
01037 std::string::size_type pos = line.find("-1");
01038 while (pos != std::string::npos) {
01039 std::string part = line.substr(0, pos);
01040 pos = line.find_first_of(",]", pos);
01041 line = line.substr(pos+1);
01042 pos = line.find("-1");
01043 if (boost::regex_match(part.c_str(), what, rx_f)) {
01044 flag = true;
01045 ulPoints[0] = std::atol(what[1].first);
01046 ulPoints[1] = std::atol(what[2].first);
01047 ulPoints[2] = std::atol(what[3].first);
01048 if (normals) {
01049
01050 MeshGeomFacet& rclFacet = clFacetAry[ulCt++];
01051 for (int i = 0; i < 3; i++)
01052 rclFacet._aclPoints[i] = aclPoints[ulPoints[i]];
01053 }
01054 else {
01055 for (int i = 0; i < 3; i++)
01056 clFacet._aclPoints[i] = aclPoints[ulPoints[i]];
01057 clFacetAry.push_back(clFacet);
01058 }
01059 seq.next(true);
01060 }
01061 }
01062 } while (std::getline(rstrIn, line) && flag);
01063 }
01064 }
01065
01066 _rclMesh = clFacetAry;
01067 return (rstrIn?true:false);
01068 }
01069
01071 bool MeshInput::LoadNastran (std::istream &rstrIn)
01072 {
01073 if ((!rstrIn) || (rstrIn.bad() == true))
01074 return false;
01075
01076 boost::regex rx_p("\\s*GRID\\s+([0-9]+)"
01077 "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
01078 "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)"
01079 "\\s+([-+]?[0-9]*)\\.?([0-9]+([eE][-+]?[0-9]+)?)\\s*");
01080 boost::regex rx_t("\\s*CTRIA3\\s+([0-9]+)\\s+([0-9]+)"
01081 "\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s*");
01082 boost::regex rx_q("\\s*CTRIA3\\s+([0-9]+)\\s+([0-9]+)"
01083 "\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s+([0-9]+)\\s*");
01084 boost::cmatch what;
01085
01086 std::string line;
01087 MeshFacet clMeshFacet;
01088 MeshPointArray vVertices;
01089 MeshFacetArray vTriangle;
01090
01091 int index;
01092 std::map <int, NODE> mNode;
01093 std::map <int, TRIA> mTria;
01094 std::map <int, QUAD> mQuad;
01095
01096 while (std::getline(rstrIn, line)) {
01097 upper(ltrim(line));
01098 if (line.find("GRID*") == 0) {
01099 assert(0);
01100 }
01101 else if (line.find("*") == 0) {
01102 assert(0);
01103 }
01104
01105 else if (line.find("GRID") == 0) {
01106 if (boost::regex_match(line.c_str(), what, rx_p)) {
01107 index = std::atol(what[1].first)-1;
01108 mNode[index].x = (float)std::atof(what[2].first);
01109 mNode[index].y = (float)std::atof(what[5].first);
01110 mNode[index].z = (float)std::atof(what[8].first);
01111 }
01112 }
01113
01114 else if (line.find("CTRIA3 ") == 0) {
01115 if (boost::regex_match(line.c_str(), what, rx_t)) {
01116 index = std::atol(what[1].first)-1;
01117 mTria[index].iV[0] = std::atol(what[3].first)-1;
01118 mTria[index].iV[1] = std::atol(what[4].first)-1;
01119 mTria[index].iV[2] = std::atol(what[5].first)-1;
01120 }
01121 }
01122
01123 else if (line.find("CQUAD4") == 0) {
01124 if (boost::regex_match(line.c_str(), what, rx_q)) {
01125 index = std::atol(what[1].first)-1;
01126 mQuad[index].iV[0] = std::atol(what[3].first)-1;
01127 mQuad[index].iV[1] = std::atol(what[4].first)-1;
01128 mQuad[index].iV[2] = std::atol(what[5].first)-1;
01129 mQuad[index].iV[3] = std::atol(what[6].first)-1;
01130 }
01131 }
01132 }
01133
01134 float fLength[2];
01135 if (mTria.empty())
01136 index = 0;
01137 else
01138 index = mTria.rbegin()->first + 1;
01139 for (std::map <int, QUAD>::iterator QI=mQuad.begin(); QI!=mQuad.end(); QI++) {
01140 for (int i = 0; i < 2; i++) {
01141 float fDx = mNode[(*QI).second.iV[i+2]].x - mNode[(*QI).second.iV[i]].x;
01142 float fDy = mNode[(*QI).second.iV[i+2]].y - mNode[(*QI).second.iV[i]].y;
01143 float fDz = mNode[(*QI).second.iV[i+2]].z - mNode[(*QI).second.iV[i]].z;
01144 fLength[i] = fDx*fDx + fDy*fDy + fDz*fDz;
01145 }
01146 if (fLength[0] < fLength[1]) {
01147 mTria[index].iV[0] = (*QI).second.iV[0];
01148 mTria[index].iV[1] = (*QI).second.iV[1];
01149 mTria[index].iV[2] = (*QI).second.iV[2];
01150
01151 mTria[index+1].iV[0] = (*QI).second.iV[0];
01152 mTria[index+1].iV[1] = (*QI).second.iV[2];
01153 mTria[index+1].iV[2] = (*QI).second.iV[3];
01154 }
01155 else {
01156 mTria[index].iV[0] = (*QI).second.iV[0];
01157 mTria[index].iV[1] = (*QI).second.iV[1];
01158 mTria[index].iV[2] = (*QI).second.iV[3];
01159
01160 mTria[index+1].iV[0] = (*QI).second.iV[1];
01161 mTria[index+1].iV[1] = (*QI).second.iV[2];
01162 mTria[index+1].iV[2] = (*QI).second.iV[3];
01163 }
01164
01165 index += 2;
01166 }
01167
01168
01169 vVertices.reserve(mNode.size());
01170 for (std::map<int, NODE>::iterator MI=mNode.begin(); MI!=mNode.end(); MI++) {
01171 vVertices.push_back(Base::Vector3f(MI->second.x, MI->second.y, MI->second.z));
01172 }
01173
01174
01175 vTriangle.reserve(mTria.size());
01176 for (std::map<int, TRIA>::iterator MI=mTria.begin(); MI!=mTria.end(); MI++) {
01177 clMeshFacet._aulPoints[0] = (*MI).second.iV[1];
01178 clMeshFacet._aulPoints[1] = (*MI).second.iV[0];
01179 clMeshFacet._aulPoints[2] = (*MI).second.iV[2];
01180 vTriangle.push_back (clMeshFacet);
01181 }
01182
01183
01184 _rclMesh.Merge(vVertices, vTriangle);
01185
01186 return true;
01187 }
01188
01190 bool MeshInput::LoadCadmouldFE (std::ifstream &rstrIn)
01191 {
01192 if ((!rstrIn) || (rstrIn.bad() == true))
01193 return false;
01194 assert(0);
01195 return false;
01196 }
01197
01198
01199
01200 std::string MeshOutput::stl_header = "MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH-"
01201 "MESH-MESH-MESH-MESH-MESH-MESH-MESH-MESH\n";
01202
01203 void MeshOutput::SetSTLHeaderData(const std::string& header)
01204 {
01205 if (header.size() > 80) {
01206 stl_header = header.substr(0, 80);
01207 }
01208 else if (header.size() < 80) {
01209 std::fill(stl_header.begin(), stl_header.end(), ' ');
01210 std::copy(header.begin(), header.end(), stl_header.begin());
01211 }
01212 else {
01213 stl_header = header;
01214 }
01215 }
01216
01217 void MeshOutput::Transform(const Base::Matrix4D& mat)
01218 {
01219 _transform = mat;
01220 if (mat != Base::Matrix4D())
01221 apply_transform = true;
01222 }
01223
01225 bool MeshOutput::SaveAny(const char* FileName, MeshIO::Format format) const
01226 {
01227
01228 Base::FileInfo fi(FileName);
01229 Base::FileInfo di(fi.dirPath().c_str());
01230 if ((fi.exists() && !fi.isWritable()) || !di.exists() || !di.isWritable())
01231 throw Base::FileException("No write permission for file",FileName);
01232
01233 MeshIO::Format fileformat = format;
01234 if (fileformat == MeshIO::Undefined) {
01235 if (fi.hasExtension("bms")) {
01236 fileformat = MeshIO::BMS;
01237 }
01238 else if (fi.hasExtension("stl")) {
01239 fileformat = MeshIO::BSTL;
01240 }
01241 else if (fi.hasExtension("ast")) {
01242 fileformat = MeshIO::ASTL;
01243 }
01244 else if (fi.hasExtension("obj")) {
01245 fileformat = MeshIO::OBJ;
01246 }
01247 else if (fi.hasExtension("off")) {
01248 fileformat = MeshIO::OFF;
01249 }
01250 else if (fi.hasExtension("ply")) {
01251 fileformat = MeshIO::PLY;
01252 }
01253 else if (fi.hasExtension("iv")) {
01254 fileformat = MeshIO::IV;
01255 }
01256 else if (fi.hasExtension("py")) {
01257 fileformat = MeshIO::PY;
01258 }
01259 else if (fi.hasExtension("wrl") || fi.hasExtension("vrml")) {
01260 fileformat = MeshIO::VRML;
01261 }
01262 else if (fi.hasExtension("wrz")) {
01263 fileformat = MeshIO::WRZ;
01264 }
01265 else if (fi.hasExtension("nas") || fi.hasExtension("bdf")) {
01266 fileformat = MeshIO::NAS;
01267 }
01268 }
01269
01270 Base::ofstream str(fi, std::ios::out | std::ios::binary);
01271
01272 if (fileformat == MeshIO::BMS) {
01273 _rclMesh.Write(str);
01274 }
01275 else if (fileformat == MeshIO::BSTL) {
01276 MeshOutput aWriter(_rclMesh);
01277 aWriter.Transform(this->_transform);
01278
01279
01280 bool ok = false;
01281 ok = aWriter.SaveBinarySTL( str );
01282 if (!ok)
01283 throw Base::FileException("Export of STL mesh failed",FileName);
01284
01285 }
01286 else if (fileformat == MeshIO::ASTL) {
01287 MeshOutput aWriter(_rclMesh);
01288 aWriter.Transform(this->_transform);
01289
01290
01291 bool ok = false;
01292 ok = aWriter.SaveAsciiSTL( str );
01293 if (!ok)
01294 throw Base::FileException("Export of STL mesh failed",FileName);
01295
01296 }
01297 else if (fileformat == MeshIO::OBJ) {
01298
01299 if (!SaveOBJ(str))
01300 throw Base::FileException("Export of OBJ mesh failed",FileName);
01301 }
01302 else if (fileformat == MeshIO::OFF) {
01303
01304 if (!SaveOFF(str))
01305 throw Base::FileException("Export of OFF mesh failed",FileName);
01306 }
01307 else if (fileformat == MeshIO::PLY) {
01308
01309 if (!SavePLY(str))
01310 throw Base::FileException("Export of PLY mesh failed",FileName);
01311 }
01312 else if (fileformat == MeshIO::IV) {
01313
01314 if (!SaveInventor(str))
01315 throw Base::FileException("Export of Inventor mesh failed",FileName);
01316 }
01317 else if (fileformat == MeshIO::PY) {
01318
01319 if (!SavePython(str))
01320 throw Base::FileException("Export of Python mesh failed",FileName);
01321 }
01322 else if (fileformat == MeshIO::VRML) {
01323
01324 App::Material clMat;
01325 if (!SaveVRML(str, clMat))
01326 throw Base::FileException("Export of VRML mesh failed",FileName);
01327 }
01328 else if (fileformat == MeshIO::WRZ) {
01329
01330
01331
01332
01333
01334
01335 zipios::GZIPOutputStream gzip(str);
01336
01337 App::Material clMat;
01338 if (!SaveVRML(gzip, clMat))
01339 throw Base::FileException("Export of compressed VRML mesh failed",FileName);
01340 }
01341 else if (fileformat == MeshIO::NAS) {
01342
01343 if (!SaveNastran(str))
01344 throw Base::FileException("Export of NASTRAN mesh failed",FileName);
01345 }
01346 else {
01347 throw Base::FileException("File format not supported", FileName);
01348 }
01349
01350 return true;
01351 }
01352
01354 bool MeshOutput::SaveAsciiSTL (std::ostream &rstrOut) const
01355 {
01356 MeshFacetIterator clIter(_rclMesh), clEnd(_rclMesh);
01357 clIter.Transform(this->_transform);
01358 const MeshGeomFacet *pclFacet;
01359 unsigned long i;
01360
01361 if (!rstrOut || rstrOut.bad() == true || _rclMesh.CountFacets() == 0)
01362 return false;
01363
01364 rstrOut.precision(6);
01365 rstrOut.setf(std::ios::fixed | std::ios::showpoint);
01366 Base::SequencerLauncher seq("saving...", _rclMesh.CountFacets() + 1);
01367
01368 rstrOut << "solid Mesh" << std::endl;
01369
01370 clIter.Begin();
01371 clEnd.End();
01372 while (clIter < clEnd) {
01373 pclFacet = &(*clIter);
01374
01375
01376 rstrOut << " facet normal " << pclFacet->GetNormal().x << " "
01377 << pclFacet->GetNormal().y << " "
01378 << pclFacet->GetNormal().z << std::endl;
01379 rstrOut << " outer loop" << std::endl;
01380
01381
01382 for (i = 0; i < 3; i++) {
01383 rstrOut << " vertex " << pclFacet->_aclPoints[i].x << " "
01384 << pclFacet->_aclPoints[i].y << " "
01385 << pclFacet->_aclPoints[i].z << std::endl;
01386 }
01387
01388 rstrOut << " endloop" << std::endl;
01389 rstrOut << " endfacet" << std::endl;
01390
01391 ++clIter;
01392 seq.next(true);
01393 }
01394
01395 rstrOut << "endsolid Mesh" << std::endl;
01396
01397 return true;
01398 }
01399
01401 bool MeshOutput::SaveBinarySTL (std::ostream &rstrOut) const
01402 {
01403 MeshFacetIterator clIter(_rclMesh), clEnd(_rclMesh);
01404 clIter.Transform(this->_transform);
01405 const MeshGeomFacet *pclFacet;
01406 uint32_t i;
01407 uint16_t usAtt;
01408 char szInfo[81];
01409
01410 if (!rstrOut || rstrOut.bad() == true )
01411 return false;
01412
01413 Base::SequencerLauncher seq("saving...", _rclMesh.CountFacets() + 1);
01414
01415 strcpy(szInfo, stl_header.c_str());
01416 rstrOut.write(szInfo, std::strlen(szInfo));
01417
01418 uint32_t uCtFts = (uint32_t)_rclMesh.CountFacets();
01419 rstrOut.write((const char*)&uCtFts, sizeof(uCtFts));
01420
01421 usAtt = 0;
01422 clIter.Begin();
01423 clEnd.End();
01424 while (clIter < clEnd) {
01425 pclFacet = &(*clIter);
01426
01427 Base::Vector3f normal = pclFacet->GetNormal();
01428 rstrOut.write((const char*)&(normal.x), sizeof(float));
01429 rstrOut.write((const char*)&(normal.y), sizeof(float));
01430 rstrOut.write((const char*)&(normal.z), sizeof(float));
01431
01432
01433 for (i = 0; i < 3; i++) {
01434 rstrOut.write((const char*)&(pclFacet->_aclPoints[i].x), sizeof(float));
01435 rstrOut.write((const char*)&(pclFacet->_aclPoints[i].y), sizeof(float));
01436 rstrOut.write((const char*)&(pclFacet->_aclPoints[i].z), sizeof(float));
01437 }
01438
01439
01440 rstrOut.write((const char*)&usAtt, sizeof(usAtt));
01441
01442 ++clIter;
01443 seq.next(true);
01444 }
01445
01446 return true;
01447 }
01448
01450 bool MeshOutput::SaveOBJ (std::ostream &rstrOut) const
01451 {
01452 const MeshPointArray& rPoints = _rclMesh.GetPoints();
01453 const MeshFacetArray& rFacets = _rclMesh.GetFacets();
01454
01455 if (!rstrOut || rstrOut.bad() == true)
01456 return false;
01457
01458 Base::SequencerLauncher seq("saving...", _rclMesh.CountPoints() + _rclMesh.CountFacets());
01459
01460
01461 if (this->apply_transform) {
01462 Base::Vector3f pt;
01463 for (MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it) {
01464 pt = this->_transform * *it;
01465 rstrOut << "v " << pt.x << " " << pt.y << " " << pt.z << std::endl;
01466 seq.next(true);
01467 }
01468 }
01469 else {
01470 for (MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it) {
01471 rstrOut << "v " << it->x << " " << it->y << " " << it->z << std::endl;
01472 seq.next(true);
01473 }
01474 }
01475
01476 for (MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it) {
01477 rstrOut << "f " << it->_aulPoints[0]+1 << " "
01478 << it->_aulPoints[1]+1 << " "
01479 << it->_aulPoints[2]+1 << std::endl;
01480 seq.next(true);
01481 }
01482
01483 return true;
01484 }
01485
01487 bool MeshOutput::SaveOFF (std::ostream &out) const
01488 {
01489 const MeshPointArray& rPoints = _rclMesh.GetPoints();
01490 const MeshFacetArray& rFacets = _rclMesh.GetFacets();
01491
01492 if (!out || out.bad() == true)
01493 return false;
01494
01495 Base::SequencerLauncher seq("saving...", _rclMesh.CountPoints() + _rclMesh.CountFacets());
01496
01497 out << "OFF" << std::endl;
01498 out << rPoints.size() << " " << rFacets.size() << " 0" << std::endl;
01499
01500
01501 if (this->apply_transform) {
01502 Base::Vector3f pt;
01503 for (MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it) {
01504 pt = this->_transform * *it;
01505 out << pt.x << " " << pt.y << " " << pt.z << std::endl;
01506 seq.next(true);
01507 }
01508 }
01509 else {
01510 for (MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it) {
01511 out << it->x << " " << it->y << " " << it->z << std::endl;
01512 seq.next(true);
01513 }
01514 }
01515
01516
01517 for (MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it) {
01518 out << "3 " << it->_aulPoints[0]
01519 << " " << it->_aulPoints[1]
01520 << " " << it->_aulPoints[2] << std::endl;
01521 seq.next(true);
01522 }
01523
01524 return true;
01525 }
01526
01527 bool MeshOutput::SavePLY (std::ostream &out) const
01528 {
01529 const MeshPointArray& rPoints = _rclMesh.GetPoints();
01530 const MeshFacetArray& rFacets = _rclMesh.GetFacets();
01531 std::size_t v_count = rPoints.size();
01532 std::size_t f_count = rFacets.size();
01533 if (!out || out.bad() == true)
01534 return false;
01535 bool saveVertexColor = (_material && _material->binding == MeshIO::PER_VERTEX
01536 && _material->diffuseColor.size() == rPoints.size());
01537 out << "ply" << std::endl
01538 << "format binary_little_endian 1.0" << std::endl
01539 << "comment Created by FreeCAD <http://free-cad.sourceforge.net>" << std::endl
01540 << "element vertex " << v_count << std::endl
01541 << "property float32 x" << std::endl
01542 << "property float32 y" << std::endl
01543 << "property float32 z" << std::endl;
01544 if (saveVertexColor) {
01545 out << "property uchar red" << std::endl
01546 << "property uchar green" << std::endl
01547 << "property uchar blue" << std::endl;
01548 }
01549 out << "element face " << f_count << std::endl
01550 << "property list uchar int vertex_index" << std::endl
01551 << "end_header" << std::endl;
01552
01553 Base::OutputStream os(out);
01554 os.setByteOrder(Base::Stream::LittleEndian);
01555 Base::Vector3f pt;
01556 for (std::size_t i = 0; i < v_count; i++) {
01557 const MeshPoint& p = rPoints[i];
01558 if (this->apply_transform) {
01559 Base::Vector3f pt = this->_transform * p;
01560 os << pt.x << pt.y << pt.z;
01561 }
01562 else {
01563 os << p.x << p.y << p.z;
01564 }
01565 if (saveVertexColor) {
01566 const App::Color& c = _material->diffuseColor[i];
01567 int r = (int)(255.0f * c.r);
01568 int g = (int)(255.0f * c.g);
01569 int b = (int)(255.0f * c.b);
01570 os << r << g << b;
01571 }
01572 }
01573 unsigned char n = 3;
01574 int f1, f2, f3;
01575 for (std::size_t i = 0; i < f_count; i++) {
01576 const MeshFacet& f = rFacets[i];
01577 f1 = (int)f._aulPoints[0];
01578 f2 = (int)f._aulPoints[1];
01579 f3 = (int)f._aulPoints[2];
01580 os << n;
01581 os << f1 << f2 << f3;
01582 }
01583
01584 return true;
01585 }
01586
01587 bool MeshOutput::SaveMeshNode (std::ostream &rstrOut)
01588 {
01589 const MeshPointArray& rPoints = _rclMesh.GetPoints();
01590 const MeshFacetArray& rFacets = _rclMesh.GetFacets();
01591
01592 if (!rstrOut || rstrOut.bad() == true)
01593 return false;
01594
01595
01596 rstrOut << "[" << std::endl;
01597 if (this->apply_transform) {
01598 Base::Vector3f pt;
01599 for (MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it) {
01600 pt = this->_transform * *it;
01601 rstrOut << "v " << pt.x << " " << pt.y << " " << pt.z << std::endl;
01602 }
01603 }
01604 else {
01605 for (MeshPointArray::_TConstIterator it = rPoints.begin(); it != rPoints.end(); ++it) {
01606 rstrOut << "v " << it->x << " " << it->y << " " << it->z << std::endl;
01607 }
01608 }
01609
01610 for (MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); ++it) {
01611 rstrOut << "f " << it->_aulPoints[0]+1 << " "
01612 << it->_aulPoints[1]+1 << " "
01613 << it->_aulPoints[2]+1 << std::endl;
01614 }
01615 rstrOut << "]" << std::endl;
01616
01617 return true;
01618 }
01619
01621 void MeshOutput::SaveXML (Base::Writer &writer) const
01622 {
01623 const MeshPointArray& rPoints = _rclMesh.GetPoints();
01624 const MeshFacetArray& rFacets = _rclMesh.GetFacets();
01625
01626
01627
01628 writer.incInd();
01629 writer.Stream() << writer.ind() << "<Points Count=\"" << _rclMesh.CountPoints() << "\">" << std::endl;
01630
01631 writer.incInd();
01632 if (this->apply_transform) {
01633 Base::Vector3f pt;
01634 for (MeshPointArray::_TConstIterator itp = rPoints.begin(); itp != rPoints.end(); itp++) {
01635 pt = this->_transform * *itp;
01636 writer.Stream() << writer.ind() << "<P "
01637 << "x=\"" << pt.x << "\" "
01638 << "y=\"" << pt.y << "\" "
01639 << "z=\"" << pt.z << "\"/>"
01640 << std::endl;
01641 }
01642 }
01643 else {
01644 for (MeshPointArray::_TConstIterator itp = rPoints.begin(); itp != rPoints.end(); itp++) {
01645 writer.Stream() << writer.ind() << "<P "
01646 << "x=\"" << itp->x << "\" "
01647 << "y=\"" << itp->y << "\" "
01648 << "z=\"" << itp->z << "\"/>"
01649 << std::endl;
01650 }
01651 }
01652 writer.decInd();
01653 writer.Stream() << writer.ind() << "</Points>" << std::endl;
01654
01655
01656 writer.Stream() << writer.ind() << "<Faces Count=\"" << _rclMesh.CountFacets() << "\">" << std::endl;
01657
01658 writer.incInd();
01659 for (MeshFacetArray::_TConstIterator it = rFacets.begin(); it != rFacets.end(); it++) {
01660 writer.Stream() << writer.ind() << "<F "
01661 << "p0=\"" << it->_aulPoints[0] << "\" "
01662 << "p1=\"" << it->_aulPoints[1] << "\" "
01663 << "p2=\"" << it->_aulPoints[2] << "\" "
01664 << "n0=\"" << it->_aulNeighbours[0] << "\" "
01665 << "n1=\"" << it->_aulNeighbours[1] << "\" "
01666 << "n2=\"" << it->_aulNeighbours[2] << "\"/>"
01667 << std::endl;
01668 }
01669 writer.decInd();
01670 writer.Stream() << writer.ind() << "</Faces>" << std::endl;
01671
01672 writer.Stream() << writer.ind() << "</Mesh>" << std::endl;
01673 writer.decInd();
01674 }
01675
01677 bool MeshOutput::SaveInventor (std::ostream &rstrOut) const
01678 {
01679 if ((!rstrOut) || (rstrOut.bad() == true) || (_rclMesh.CountFacets() == 0))
01680 return false;
01681
01682 MeshFacetIterator clIter(_rclMesh), clEnd(_rclMesh);
01683 clIter.Transform(this->_transform);
01684 MeshPointIterator clPtIter(_rclMesh), clPtEnd(_rclMesh);
01685 clPtIter.Transform(this->_transform);
01686 const MeshGeomFacet* pclFacet;
01687 unsigned long ulAllFacets = _rclMesh.CountFacets();
01688
01689 Base::SequencerLauncher seq("Saving...", _rclMesh.CountFacets() + 1);
01690 rstrOut.precision(6);
01691 rstrOut.setf(std::ios::fixed | std::ios::showpoint);
01692
01693
01694 rstrOut << "#Inventor V2.1 ascii\n" << std::endl;
01695 rstrOut << "# Created by FreeCAD <http://free-cad.sourceforge.net>" << std::endl;
01696 rstrOut << "# Triangle mesh contains " << _rclMesh.CountPoints() << " vertices"
01697 << " and " << _rclMesh.CountFacets() << " faces" << std::endl;
01698 rstrOut << "Separator {\n" << std::endl;
01699 rstrOut << " Label {" << std::endl;
01700 rstrOut << " label \"Triangle mesh\"\n }" << std::endl;
01701
01702
01703 rstrOut << " Normal { " << std::endl;
01704 rstrOut << " vector [ ";
01705
01706 clIter.Begin();
01707 clEnd.End();
01708
01709 pclFacet = &(*clIter);
01710 rstrOut << pclFacet->GetNormal().x << " "
01711 << pclFacet->GetNormal().y << " "
01712 << pclFacet->GetNormal().z;
01713 ++clIter;
01714
01715 while (clIter < clEnd) {
01716 pclFacet = &(*clIter);
01717 rstrOut << ",\n "
01718 << pclFacet->GetNormal().x << " "
01719 << pclFacet->GetNormal().y << " "
01720 << pclFacet->GetNormal().z;
01721 ++clIter;
01722
01723 seq.next(true);
01724 }
01725
01726 rstrOut << " ]\n\n }" << std::endl;
01727
01728
01729 rstrOut << " NormalBinding {\n value PER_FACE\n }" << std::endl;
01730 rstrOut << " Coordinate3 {\n point [ ";
01731
01732 clPtIter.Begin();
01733 clPtEnd.End();
01734
01735 rstrOut << clPtIter->x << " "
01736 << clPtIter->y << " "
01737 << clPtIter->z;
01738 ++clPtIter;
01739
01740 while (clPtIter < clPtEnd) {
01741 rstrOut << ",\n "
01742 << clPtIter->x << " "
01743 << clPtIter->y << " "
01744 << clPtIter->z;
01745 ++clPtIter;
01746 seq.next(true);
01747 }
01748
01749 rstrOut << " ]\n\n }" << std::endl;
01750
01751
01752 rstrOut << " IndexedFaceSet {\n coordIndex [ ";
01753
01754 const MeshFacet clFacet = _rclMesh.GetFacets()[0];
01755 rstrOut << clFacet._aulPoints[0] << ", "
01756 << clFacet._aulPoints[1] << ", "
01757 << clFacet._aulPoints[2] << ", -1";
01758
01759 unsigned long i = 1;
01760 while (i < ulAllFacets) {
01761
01762 const MeshFacet clFacet = _rclMesh.GetFacets()[i];
01763 if ( i%2==0 ) {
01764 rstrOut << ",\n "
01765 << clFacet._aulPoints[0] << ", "
01766 << clFacet._aulPoints[1] << ", "
01767 << clFacet._aulPoints[2] << ", -1";
01768 }
01769 else {
01770 rstrOut << ", "
01771 << clFacet._aulPoints[0] << ", "
01772 << clFacet._aulPoints[1] << ", "
01773 << clFacet._aulPoints[2] << ", -1";
01774 }
01775 ++i;
01776 }
01777
01778 rstrOut << " ]\n\n }" << std::endl;
01779 rstrOut << "#End of triangle mesh \n}\n" << std::endl;
01780
01781 return true;
01782 }
01783
01785 bool MeshOutput::SaveNastran (std::ostream &rstrOut) const
01786 {
01787 if ((!rstrOut) || (rstrOut.bad() == true) || (_rclMesh.CountFacets() == 0))
01788 return false;
01789
01790 MeshPointIterator clPIter(_rclMesh);
01791 clPIter.Transform(this->_transform);
01792 MeshFacetIterator clTIter(_rclMesh);
01793 int iIndx = 1;
01794
01795 Base::SequencerLauncher seq("Saving...", _rclMesh.CountFacets() + 1);
01796
01797 rstrOut.precision(3);
01798 rstrOut.setf(std::ios::fixed | std::ios::showpoint);
01799 for (clPIter.Init(); clPIter.More(); clPIter.Next()) {
01800 float x = clPIter->x;
01801 float y = clPIter->y;
01802 float z = clPIter->z;
01803
01804 rstrOut << "GRID";
01805
01806 rstrOut << std::setfill(' ') << std::setw(12) << iIndx;
01807 rstrOut << std::setfill(' ') << std::setw(16) << x;
01808 rstrOut << std::setfill(' ') << std::setw(8) << y;
01809 rstrOut << std::setfill(' ') << std::setw(8) << z;
01810 rstrOut << std::endl;
01811
01812 iIndx++;
01813 seq.next();
01814 }
01815
01816 iIndx = 1;
01817 for (clTIter.Init(); clTIter.More(); clTIter.Next()) {
01818 rstrOut << "CTRIA3";
01819
01820 rstrOut << std::setfill(' ') << std::setw(10) << iIndx;
01821 rstrOut << std::setfill(' ') << std::setw(8) << (int)0;
01822 rstrOut << std::setfill(' ') << std::setw(8) << clTIter.GetIndices()._aulPoints[1]+1;
01823 rstrOut << std::setfill(' ') << std::setw(8) << clTIter.GetIndices()._aulPoints[0]+1;
01824 rstrOut << std::setfill(' ') << std::setw(8) << clTIter.GetIndices()._aulPoints[2]+1;
01825 rstrOut <<std::endl;
01826
01827 iIndx++;
01828 seq.next();
01829 }
01830
01831 rstrOut << "ENDDATA";
01832
01833 return true;
01834 }
01835
01837 bool MeshOutput::SaveCadmouldFE (std::ostream &rstrOut) const
01838 {
01839 return false;
01840 }
01841
01843 bool MeshOutput::SavePython (std::ostream &str) const
01844 {
01845 if ((!str) || (str.bad() == true) || (_rclMesh.CountFacets() == 0))
01846 return false;
01847
01848 MeshFacetIterator clIter(_rclMesh);
01849 clIter.Transform(this->_transform);
01850 str.precision(4);
01851 str.setf(std::ios::fixed | std::ios::showpoint);
01852
01853 str << "faces = [" << std::endl;
01854 for (clIter.Init(); clIter.More(); clIter.Next()) {
01855 const MeshGeomFacet& rFacet = *clIter;
01856 for (int i = 0; i < 3; i++) {
01857 str << "[" << rFacet._aclPoints[i].x
01858 << "," << rFacet._aclPoints[i].y
01859 << "," << rFacet._aclPoints[i].z
01860 << "],";
01861 }
01862 str << std::endl;
01863 }
01864
01865 str << "]" << std::endl;
01866
01867 return true;
01868 }
01869
01870
01871
01872 class MeshVRML
01873 {
01874 public:
01875 MeshVRML (const MeshKernel &rclM, const Base::Matrix4D&);
01876 MeshVRML (const MeshKernel &rclM, const Base::Matrix4D&,VRMLInfo* pclVRMLInfo);
01877 ~MeshVRML (void){}
01878
01879 bool Save (std::ostream &rstrOut, const App::Material &rclMat) const;
01880 bool Save (std::ostream &rstrOut, const std::vector<App::Color> &raclColor,
01881 const App::Material &rclMat, bool bColorPerVertex = true) const;
01882
01883 protected:
01884 void WriteVRMLHeaderInfo(std::ostream &rstrOut) const;
01885 void WriteVRMLAnnotations(std::ostream &rstrOut) const;
01886 void WriteVRMLViewpoints(std::ostream &rstrOut) const;
01887
01888 const MeshKernel &_rclMesh;
01889 Base::Matrix4D _transform;
01890 VRMLInfo* _pclVRMLInfo;
01891 };
01892
01894 bool MeshOutput::SaveVRML (std::ostream &rstrOut, const App::Material &rclMat) const
01895 {
01896 return MeshVRML(_rclMesh, this->_transform).Save(rstrOut, rclMat);
01897 }
01898
01899 MeshVRML::MeshVRML (const MeshKernel &rclM, const Base::Matrix4D& trf)
01900 : _rclMesh(rclM), _transform(trf), _pclVRMLInfo(0)
01901 {
01902 }
01903
01904 MeshVRML::MeshVRML (const MeshKernel &rclM, const Base::Matrix4D& trf, VRMLInfo* pclVRMLInfo)
01905 : _rclMesh(rclM), _transform(trf), _pclVRMLInfo(pclVRMLInfo)
01906 {
01907 }
01908
01909 bool MeshVRML::Save (std::ostream &rstrOut, const std::vector<App::Color> &raclColor,
01910 const App::Material &rclMat, bool bColorPerVertex) const
01911 {
01912 if ((!rstrOut) || (rstrOut.bad() == true) || (_rclMesh.CountFacets() == 0))
01913 return false;
01914
01915 Base::BoundBox3f clBB = _rclMesh.GetBoundBox();
01916 Base::Vector3f clCenter = clBB.CalcCenter();
01917
01918 Base::SequencerLauncher seq("Saving VRML file...",
01919 _rclMesh.CountPoints() + raclColor.size() + _rclMesh.CountFacets());
01920
01921 rstrOut << "#VRML V2.0 utf8" << std::endl;
01922
01923 if (_pclVRMLInfo)
01924 WriteVRMLHeaderInfo(rstrOut);
01925 else
01926 rstrOut << "WorldInfo {\n"
01927 << " title \"Exported tringle mesh to VRML97\"\n"
01928 << " info [\"Created by FreeCAD\"\n"
01929 << " \"<http://free-cad.sourceforge.net>\"]\n"
01930 << "}\n";
01931
01932
01933
01934
01935
01936
01937 if (_pclVRMLInfo) {
01938 float r = float(_pclVRMLInfo->_clColor.r) / 255.0f;
01939 float g = float(_pclVRMLInfo->_clColor.g) / 255.0f;
01940 float b = float(_pclVRMLInfo->_clColor.b) / 255.0f;
01941 rstrOut.precision(1);
01942 rstrOut.setf(std::ios::fixed | std::ios::showpoint);
01943 rstrOut << "Background\n{\n skyAngle 1.57\n skyColor "
01944 << r << " " << g << " " << b << "\n}" << std::endl;
01945 }
01946 else {
01947 rstrOut << "Background\n{\n skyAngle 1.57\n skyColor "
01948 << "0.1 0.2 0.2\n}" << std::endl;
01949 }
01950
01951
01952 rstrOut.precision(3);
01953 rstrOut.setf(std::ios::fixed | std::ios::showpoint);
01954 rstrOut << "Transform\n{\n"
01955 << "scale 1 1 1\n"
01956 << "rotation 0 0 1 0\n"
01957 << "scaleOrientation 0 0 1 0\n"
01958 << "bboxCenter 0 0 0\n"
01959 << "bboxSize "
01960 << clBB.LengthX() << " "
01961 << clBB.LengthY() << " "
01962 << clBB.LengthZ() << std::endl;
01963 rstrOut << "center "
01964 << 0.0f << " "
01965 << 0.0f << " "
01966 << 0.0f << std::endl;
01967 rstrOut << "translation "
01968 << 0.0f << " "
01969 << 0.0f << " "
01970 << 0.0f << std::endl;
01971
01972 rstrOut << "children\n[\n";
01973 rstrOut << "Shape\n{" << std::endl;
01974
01975
01976 rstrOut << " appearance Appearance\n {\n material Material\n {\n";
01977 rstrOut << " ambientIntensity 0.2" << std::endl;
01978
01979 rstrOut.precision(2);
01980 rstrOut.setf(std::ios::fixed | std::ios::showpoint);
01981 if (raclColor.size() > 0) {
01982 rstrOut << " diffuseColor 0.2 0.2 0.2\n";
01983 rstrOut << " emissiveColor 0.2 0.2 0.2\n";
01984 rstrOut << " specularColor 0.2 0.2 0.2\n";
01985 }
01986 else {
01987 App::Color clCol;
01988 clCol = rclMat.diffuseColor;
01989 rstrOut << " diffuseColor "
01990 << clCol.r << " "
01991 << clCol.g << " "
01992 << clCol.b << std::endl;
01993 clCol = rclMat.emissiveColor;
01994 rstrOut << " emissiveColor "
01995 << clCol.r << " "
01996 << clCol.g << " "
01997 << clCol.b << std::endl;
01998 clCol = rclMat.specularColor;
01999 rstrOut << " specularColor "
02000 << clCol.r << " "
02001 << clCol.g << " "
02002 << clCol.b << std::endl;
02003 }
02004
02005 rstrOut << " shininess " << rclMat.shininess << std::endl;
02006 rstrOut << " transparency " << rclMat.transparency << std::endl;
02007 rstrOut << " }\n }" << std::endl;
02008
02009
02010
02011 rstrOut << " geometry IndexedFaceSet\n {\n";
02012 rstrOut << " solid FALSE\n";
02013
02014
02015 rstrOut << " coord Coordinate\n {\n point\n [\n";
02016 MeshPointIterator pPIter(_rclMesh);
02017 pPIter.Transform(this->_transform);
02018 unsigned long i = 0, k = _rclMesh.CountPoints();
02019 rstrOut.precision(3);
02020 rstrOut.setf(std::ios::fixed | std::ios::showpoint);
02021 for (pPIter.Init(); pPIter.More(); pPIter.Next()) {
02022 rstrOut << " "
02023 << pPIter->x << " "
02024 << pPIter->y << " "
02025 << pPIter->z;
02026 if (i++ < (k-1))
02027 rstrOut << ",\n";
02028 else
02029 rstrOut << "\n";
02030
02031 seq.next();
02032 }
02033
02034 rstrOut << " ]\n }" << std::endl;
02035
02036 rstrOut << " colorPerVertex "
02037 << (bColorPerVertex ? "TRUE" : "FALSE") << std::endl;
02038
02039 if (raclColor.size() > 0) {
02040
02041 rstrOut << " color Color\n {\n color\n [\n";
02042 rstrOut.precision(3);
02043 rstrOut.setf(std::ios::fixed | std::ios::showpoint);
02044 for (std::vector<App::Color>::const_iterator pCIter = raclColor.begin();
02045 pCIter != raclColor.end(); pCIter++) {
02046 rstrOut << " "
02047 << float(pCIter->r) / 255.0f << " "
02048 << float(pCIter->g) / 255.0f << " "
02049 << float(pCIter->b) / 255.0f;
02050 if (pCIter < (raclColor.end() - 1))
02051 rstrOut << ",\n";
02052 else
02053 rstrOut << "\n";
02054 seq.next();
02055 }
02056
02057 rstrOut << " ]\n }" << std::endl;
02058 }
02059
02060
02061 rstrOut << " coordIndex\n [\n";
02062 MeshFacetIterator pFIter(_rclMesh);
02063 pFIter.Transform(this->_transform);
02064 i = 0, k = _rclMesh.CountFacets();
02065 for (pFIter.Init(); pFIter.More(); pFIter.Next()) {
02066 MeshFacet clFacet = pFIter.GetIndices();
02067 rstrOut << " "
02068 << clFacet._aulPoints[0] << ", "
02069 << clFacet._aulPoints[1] << ", "
02070 << clFacet._aulPoints[2] << ", -1";
02071 if (i++ < (k-1))
02072 rstrOut << ",\n";
02073 else
02074 rstrOut << "\n";
02075
02076 seq.next();
02077 }
02078
02079 rstrOut << " ]\n }" << std::endl;
02080 rstrOut << "}" << std::endl;
02081
02082
02083 rstrOut << "]\n}" << std::endl;
02084
02085
02086 rstrOut.precision(3);
02087 rstrOut.setf(std::ios::fixed | std::ios::showpoint);
02088 for (i = 0; i < 6; i++) {
02089 rstrOut << "Viewpoint\n{\n"
02090 << " jump TRUE\n";
02091
02092 Base::Vector3f clPos = clCenter;
02093 float fLen = clBB.CalcDiagonalLength();
02094 switch (i)
02095 {
02096 case 0:
02097 {
02098 Vector at, pos, up, rot_axis;
02099 double rot_angle;
02100 at.x = clPos.x; at.y = clPos.y; at.z = clPos.z;
02101 pos.x = clPos.x; pos.y = clPos.y; pos.z = clPos.z + fLen;
02102 up.x = 0.0; up.y = 1.0; up.z = 0.0;
02103 Convert_Camera_Model(&pos, &at, &up, &rot_axis, &rot_angle);
02104 rstrOut << " orientation "
02105 << rot_axis.x << " "
02106 << rot_axis.y << " "
02107 << rot_axis.z << " "
02108 << rot_angle << "\n";
02109 rstrOut << " description \"top\"\n";
02110 clPos.z += fLen;
02111 break;
02112 }
02113 case 1:
02114 {
02115 Vector at, pos, up, rot_axis;
02116 double rot_angle;
02117 at.x = clPos.x; at.y = clPos.y; at.z = clPos.z;
02118 pos.x = clPos.x; pos.y = clPos.y; pos.z = clPos.z - fLen;
02119 up.x = 0.0; up.y = -1.0; up.z = 0.0;
02120 Convert_Camera_Model(&pos, &at, &up, &rot_axis, &rot_angle);
02121 rstrOut << " orientation "
02122 << rot_axis.x << " "
02123 << rot_axis.y << " "
02124 << rot_axis.z << " "
02125 << rot_angle << "\n";
02126 rstrOut << " description \"bottom\"\n";
02127 clPos.z -= fLen;
02128 break;
02129 }
02130 case 2:
02131 {
02132 Vector at, pos, up, rot_axis;
02133 double rot_angle;
02134 at.x = clPos.x; at.y = clPos.y; at.z = clPos.z;
02135 pos.x = clPos.x; pos.y = clPos.y - fLen; pos.z = clPos.z;
02136 up.x = 0.0; up.y = 0.0; up.z = 1.0;
02137 Convert_Camera_Model(&pos, &at, &up, &rot_axis, &rot_angle);
02138 rstrOut << " orientation "
02139 << rot_axis.x << " "
02140 << rot_axis.y << " "
02141 << rot_axis.z << " "
02142 << rot_angle << "\n";
02143 rstrOut << " description \"front\"\n";
02144 clPos.y -= fLen;
02145 break;
02146 }
02147 case 3:
02148 {
02149 Vector at, pos, up, rot_axis;
02150 double rot_angle;
02151 at.x = clPos.x; at.y = clPos.y; at.z = clPos.z;
02152 pos.x = clPos.x; pos.y = clPos.y + fLen; pos.z = clPos.z;
02153 up.x = 0.0; up.y = 0.0; up.z = 1.0;
02154 Convert_Camera_Model(&pos, &at, &up, &rot_axis, &rot_angle);
02155 rstrOut << " orientation "
02156 << rot_axis.x << " "
02157 << rot_axis.y << " "
02158 << rot_axis.z << " "
02159 << rot_angle << "\n";
02160 rstrOut << " description \"back\"\n";
02161 clPos.y += fLen;
02162 break;
02163 }
02164 case 4:
02165 {
02166 Vector at, pos, up, rot_axis;
02167 double rot_angle;
02168 at.x = clPos.x; at.y = clPos.y; at.z = clPos.z;
02169 pos.x = clPos.x - fLen; pos.y = clPos.y; pos.z = clPos.z;
02170 up.x = 0.0; up.y = 0.0; up.z = 1.0;
02171 Convert_Camera_Model(&pos, &at, &up, &rot_axis, &rot_angle);
02172 rstrOut << " orientation "
02173 << rot_axis.x << " "
02174 << rot_axis.y << " "
02175 << rot_axis.z << " "
02176 << rot_angle << "\n";
02177 rstrOut << " description \"right\"\n";
02178 clPos.x -= fLen;
02179 break;
02180 }
02181 case 5:
02182 {
02183 Vector at, pos, up, rot_axis;
02184 double rot_angle;
02185 at.x = clPos.x; at.y = clPos.y; at.z = clPos.z;
02186 pos.x = clPos.x + fLen; pos.y = clPos.y; pos.z = clPos.z;
02187 up.x = 0.0; up.y = 0.0; up.z = 1.0;
02188 Convert_Camera_Model(&pos, &at, &up, &rot_axis, &rot_angle);
02189 rstrOut << " orientation "
02190 << rot_axis.x << " "
02191 << rot_axis.y << " "
02192 << rot_axis.z << " "
02193 << rot_angle << "\n";
02194 rstrOut << " description \"left\"\n";
02195 clPos.x += fLen;
02196 break;
02197 }
02198 }
02199
02200 rstrOut << " position "
02201 << clPos.x << " "
02202 << clPos.y << " "
02203 << clPos.z << "\n}" << std::endl;
02204 }
02205
02206
02207 rstrOut << "NavigationInfo\n{\n"
02208 << " avatarSize [0.25, 1.6, 0.75]\n"
02209 << " headlight TRUE\n"
02210 << " speed 1.0\n"
02211 << " type \"EXAMINE\"\n"
02212 << " visibilityLimit 0.0\n"
02213 << "}" << std::endl;
02214
02215
02216 if (_pclVRMLInfo)
02217 WriteVRMLViewpoints(rstrOut);
02218
02219 if (_pclVRMLInfo)
02220 WriteVRMLAnnotations(rstrOut);
02221
02222 return true;
02223 }
02224
02225 void MeshVRML::WriteVRMLHeaderInfo(std::ostream &rstrOut) const
02226 {
02227
02228
02229 rstrOut << "#=================================================#\n#\n"
02230 << "# F I L E I N F O R M A T I O N\n#\n"
02231 << "# This file was created by " << _pclVRMLInfo->_clAuthor << "\n"
02232 << "# Creation Date: " << _pclVRMLInfo->_clDate << "\n"
02233 << "# Company: " << _pclVRMLInfo->_clCompany << "\n";
02234 std::vector<std::string>::const_iterator sIt = _pclVRMLInfo->_clComments.begin();
02235 rstrOut << "# Further comments: " << *sIt << "\n";
02236 for (sIt++ ;sIt != _pclVRMLInfo->_clComments.end(); ++sIt) {
02237 rstrOut << "# " << *sIt << "\n";
02238 }
02239 rstrOut << "#=================================================#\n" << std::endl;
02240 }
02241
02242 void MeshVRML::WriteVRMLAnnotations(std::ostream &rstrOut) const
02243 {
02244 float r = float(_pclVRMLInfo->_clColor.r) / 255.0f;
02245 float g = float(_pclVRMLInfo->_clColor.g) / 255.0f;
02246 float b = float(_pclVRMLInfo->_clColor.b) / 255.0f;
02247 float textr = 1.0f - r;
02248 float textg = 1.0f - g;
02249 float textb = 1.0f - b;
02250
02251 if (fabs(textr-r) < 0.05)
02252 textr = 1.0f;
02253 if (fabs(textg-g) < 0.05)
02254 textg = 1.0f;
02255 if (fabs(textb-b) < 0.05)
02256 textb = 1.0f;
02257
02258
02259 rstrOut << "DEF User ProximitySensor {\n"
02260 << " size 1000000 1000000 1000000\n"
02261 << "}\n"
02262 << "\n"
02263 << " Group { \n"
02264 << " children [\n"
02265 << " DEF UserPos Transform {\n"
02266 << " children [\n"
02267 << " # Text position\n"
02268 << " Transform {\n"
02269 << " translation -1.0 -0.75 -2\n"
02270 << " children [\n"
02271 << " Transform {\n"
02272 << " translation 1.95 0.75 0\n"
02273 << " children [\n"
02274 << " Shape {\n";
02275 if (_pclVRMLInfo->_bSavePicture) {
02276 rstrOut << " appearance Appearance {\n"
02277 << " texture ImageTexture { \n"
02278 << " url \""
02279 << _pclVRMLInfo->_clPicFileName
02280 << "\"\n"
02281 << " repeatS FALSE\n"
02282 << " repeatT FALSE\n"
02283 << " }\n"
02284 << " }\n"
02285 << " geometry IndexedFaceSet {\n"
02286 << " coord Coordinate { point [ -0.08 -0.8 0,\n"
02287 << " 0.08 -0.8 0,\n"
02288 << " 0.08 0.8 0,\n"
02289 << " -0.08 0.8 0\n"
02290 << " ]\n"
02291 << " }\n"
02292 << " coordIndex [0,1,2,3, -1]\n"
02293 << " texCoord TextureCoordinate {\n"
02294 << " point [ 0 0,\n"
02295 << " 1 0,\n"
02296 << " 1 1,\n"
02297 << " 0 1 ]\n"
02298 << " }\n"
02299 << " texCoordIndex [ 0, 1, 2, 3, -1 ]\n\n"
02300 << " solid FALSE\n"
02301 << " }" << std::endl;
02302 }
02303
02304 rstrOut << " }\n"
02305 << " ]\n"
02306 << " }\n"
02307 << " Shape {\n"
02308 << " appearance DEF COAP Appearance {\n"
02309 << " material Material {diffuseColor "
02310 << textr << " "
02311 << textg << " "
02312 << textb << "}} # text color\n"
02313 << " geometry DEF MyText Text {\n"
02314 << " string \""
02315 << _pclVRMLInfo->_clAnnotation
02316 << "\"\n"
02317 << " fontStyle DEF COFS FontStyle {\n"
02318 << " family [ \"Verdana\", \"Arial\", \"Helvetica\" ]\n"
02319 << " size 0.08 # text size\n"
02320 << " }\n"
02321 << " }\n"
02322 << " }\n"
02323 << " ]\n"
02324 << " }\n"
02325 << " ]\n"
02326 << " }\n"
02327 << " ]\n"
02328 << " }\n"
02329 << ""
02330 << "ROUTE User.position_changed TO UserPos.set_translation\n"
02331 << "ROUTE User.orientation_changed TO UserPos.set_rotation" << std::endl;
02332 }
02333
02334 void MeshVRML::WriteVRMLViewpoints(std::ostream &rstrOut) const
02335 {
02336
02337
02338 rstrOut.precision(3);
02339 rstrOut.setf(std::ios::fixed | std::ios::showpoint);
02340 Base::BoundBox3f clBB = _rclMesh.GetBoundBox();
02341 Base::Vector3f clCenter = clBB.CalcCenter();
02342 for (std::vector<VRMLViewpointData>::iterator it = _pclVRMLInfo->_clViewpoints.begin(); it != _pclVRMLInfo->_clViewpoints.end(); ++it)
02343 {
02344
02345 Base::Vector3f u,v,w;
02346 v = it->clVRefUp;
02347 w = it->clVRefPln;
02348 u = v % w;
02349 u.Normalize();
02350 v.Normalize();
02351 w.Normalize();
02352
02353
02354
02355 Base::Vector3f p_uvw, p_xyz;
02356 p_uvw = it->clPRefPt;
02357 p_xyz.x = u.x*p_uvw.x+v.x*p_uvw.y+w.x*p_uvw.z;
02358 p_xyz.y = u.y*p_uvw.x+v.y*p_uvw.y+w.y*p_uvw.z;
02359 p_xyz.z = u.z*p_uvw.x+v.z*p_uvw.y+w.z*p_uvw.z;
02360 p_xyz = p_xyz + it->clVRefPt;
02361
02362 float t = (clCenter - p_xyz)*w;
02363 Base::Vector3f a = p_xyz + t*w;
02364
02365 Vector at, pos, up, rot_axis;
02366 double rot_angle;
02367
02368 float fDistance = (float)(it->dVmax - it->dVmin);
02369 Base::Vector3f p = a + fDistance * w;
02370 pos.x = p.x; pos.y = p.y; pos.z = p.z;
02371 at.x = a.x; at.y = a.y; at.z = a.z;
02372 up.x = v.x; up.y = v.y; up.z = v.z;
02373
02374 Convert_Camera_Model(&pos, &at, &up, &rot_axis, &rot_angle);
02375
02376 rstrOut << "Viewpoint\n{\n"
02377 << " jump TRUE\n"
02378 << " orientation "
02379 << rot_axis.x << " "
02380 << rot_axis.y << " "
02381 << rot_axis.z << " "
02382 << rot_angle << "\n";
02383 rstrOut << " description \"" << it->clName << "\"\n";
02384 rstrOut << " position "
02385 << pos.x << " "
02386 << pos.y << " "
02387 << pos.z << "\n}" << std::endl;
02388 }
02389 }
02390
02391 bool MeshVRML::Save (std::ostream &rstrOut, const App::Material &rclMat) const
02392 {
02393 std::vector<App::Color> aclDummy;
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404 return Save(rstrOut, aclDummy, rclMat, false);
02405 }
02406