MeshIO.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2005 Imetric 3D GmbH                                    *
00003  *                                                                         *
00004  *   This file is part of the FreeCAD CAx development system.              *
00005  *                                                                         *
00006  *   This library is free software; you can redistribute it and/or         *
00007  *   modify it under the terms of the GNU Library General Public           *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2 of the License, or (at your option) any later version.      *
00010  *                                                                         *
00011  *   This library  is distributed in the hope that it will be useful,      *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00014  *   GNU Library General Public License for more details.                  *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Library General Public     *
00017  *   License along with this library; see the file COPYING.LIB. If not,    *
00018  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00019  *   Suite 330, Boston, MA  02111-1307, USA                                *
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 /* Define a vector.  */
00109 typedef struct _Vector
00110         {
00111                 double  x;
00112                 double  y;
00113                 double  z;
00114         } Vector, *VectorPtr;
00115 
00116 /* Usage by CMeshNastran, CMeshCadmouldFE. Added by Sergey Sukhov (26.04.2002)*/
00117 struct NODE {float x, y, z;};
00118 struct TRIA {int iV[3];};
00119 struct QUAD {int iV[4];};
00120 
00121 /* Takes the modulus of v */
00122 #define VMod(v)         (sqrt((v).x*(v).x + (v).y*(v).y + (v).z*(v).z))
00123 
00124 /* Returns the dot product of v1 & v2 */
00125 #define VDot(v1, v2)    ((v1).x*(v2).x + (v1).y*(v2).y + (v1).z*(v2).z)
00126 
00127 /* Fills the fields of a vector.        */
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         /* The quaternion requires half angles. */
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         /* n = (norm)(pos - at) */
00227         VSub(*at, *pos, n);
00228         VUnit(n, temp_d, n);
00229 
00230         /* v = (norm)(view_up - (view_up.n)n) */
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                 /* Already aligned, or maybe inverted. */
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         /* norm_quat now holds the rotation needed to line up the view directions.
00259         ** We need to find the rotation to align the up vectors also.
00260         */
00261 
00262         /* Need to rotate the world y vector to see where it ends up. */
00263         /* Find the inverse rotation. */
00264         inv_norm_quat.real_part = norm_quat.real_part;
00265         VScalarMul(norm_quat.vect_part, -1, inv_norm_quat.vect_part);
00266 
00267         /* Rotate the y. */
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         /* Now need to find out how much to rotate about n to line up y. */
00275         VCross(new_y, v, temp_v);
00276         if ( VDot(temp_v, temp_v) < 1.e-8 )
00277         {
00278                 /* The old and new may be pointing in the same or opposite. Need
00279                 ** to generate a vector perpendicular to the old or new y.
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         /* rot_y_quat holds the rotation about the initial camera direction needed
00289         ** to align the up vectors in the final position.
00290         */
00291 
00292         /* Put the 2 rotations together. */
00293         rot_quat = QQMul(&rot_y_quat, &norm_quat);
00294 
00295         /* Extract the axis and angle from the quaternion. */
00296         Quaternion_To_Axis_Angle(&rot_quat, res_axis, res_angle);
00297 }
00298 
00299 // --------------------------------------------------------------
00300 
00301 bool MeshInput::LoadAny(const char* FileName)
00302 {
00303     // ask for read permission
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         // read file
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     // Read in 50 characters from position 80 on and check for keywords like 'SOLID', 'FACET', 'NORMAL',
00355     // 'VERTEX', 'ENDFACET' or 'ENDLOOP'.
00356     // As the file can be binary with one triangle only we must not read in more than (max.) 54 bytes because
00357     // the file size has only 134 bytes in this case. On the other hand we must overread the first 80 bytes
00358     // because it can happen that the file is binary but contains one of these keywords.
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     // if we have a binary STL with a single triangle we can only read-in 50 bytes
00365     if (ulCt > 1)
00366         ulBytes = 100;
00367     // Either it's really an invalid STL file or it's just empty. In this case the number of facets must be 0.
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             // probably binary STL
00377             buf->pubseekoff(0, std::ios::beg, std::ios::in);
00378             return LoadBinarySTL(rstrIn);
00379         }
00380         else {
00381             // Ascii STL
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; // Throw the same instance of Base::MemoryException
00389     }
00390     catch (const Base::AbortException&) {
00391         _rclMesh.Clear();
00392         return false;
00393     }
00394     catch (const Base::Exception&) {
00395         _rclMesh.Clear();
00396         throw;  // Throw the same instance of Base::Exception
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             // starts a new segment
00451             if (readvertices) {
00452                 readvertices = false;
00453                 segment++;
00454             }
00455 
00456             // 3-vertex face
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             // starts a new segment
00466             if (readvertices) {
00467                 readvertices = false;
00468                 segment++;
00469             }
00470 
00471             // 4-vertex face
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(); // remove all data before
00488     // Don't use Assign() because Merge() checks which points are really needed.
00489     // This method sets already the correct neighbourhood
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     // http://local.wasp.uwa.edu.au/~pbourke/dataformats/ply/
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     // read in the first three characters
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; // wrong header
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; // empty line
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                 // wrong format version
00573                 return false;
00574             }
00575             if (version != "1.0") {
00576                 // wrong version
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; // end of the header, now read the data
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(); // remove all data before
00694     // Don't use Assign() because Merge() checks which points are really needed.
00695     // This method sets already the correct neighbourhood
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(); // remove all data before
00748     // Don't use Assign() because Merge() checks which points are really needed.
00749     // This method sets already the correct neighbourhood
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     // count facets
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         // prevent from reading EOF (as I don't know how to reread the file then)
00789         else if (rstrIn.tellg() > ulSize)
00790             break;
00791         else if (line.find("ENDSOLID") != std::string::npos)
00792             break;
00793     }
00794 
00795     // restart from the beginning
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     // Header-Info ueberlesen
00840     rstrIn.read(szInfo, sizeof(szInfo));
00841 
00842     // Anzahl Facets
00843     rstrIn.read((char*)&ulCt, sizeof(ulCt));
00844     if (rstrIn.bad() == true)
00845         return false;
00846 
00847     // get file size and calculate the number of facets
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     // compare the calculated with the read value
00860     if (ulCt > ulFac)
00861         return false;// not a valid STL file
00862  
00863     MeshBuilder builder(this->_rclMesh);
00864     builder.Initialize(ulCt);
00865 
00866     for (uint32_t i = 0; i < ulCt; i++) {
00867         // read normal, points
00868         rstrIn.read((char*)&clVects, sizeof(clVects));
00869 
00870         std::swap(clVects[0], clVects[3]);
00871         builder.AddFacet(clVects);
00872 
00873         // overread 2 bytes attribute
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 //  reader.readElement("Mesh");
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     // get file size and estimate the number of lines
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     // We have approx. 30 characters per line
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         // read the normals if they are defined
00965         if (!normals && line.find("NORMAL {") != std::string::npos) {
00966             float fX, fY, fZ;
00967             normals = true; // okay, the normals are set by an SoNormal node
00968             flag = true;
00969             // Get the next line and check for the normal field which might begin
00970             // with the first vector already i.e. it's of the form 'vector [ 0.0 0.0 1.0,'
00971             // This is a special case to support also file formats directly written by
00972             // Inventor 2.1 classes.
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); // 8 = length of 'VECTOR ['
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); // allow to cancel
00987                 } else 
00988                     flag = false;
00989             } while (std::getline(rstrIn, line) && flag);
00990         }
00991         // read the coordinates
00992         else if (!points && line.find("COORDINATE3 {") != std::string::npos) {
00993             Base::Vector3f clPoint;
00994             points = true; // the SoCoordinate3 node
00995             flag = true;
00996             // Get the next line and check for the points field which might begin
00997             // with the first point already i.e. it's of the form 'point [ 0.0 0.0 0.0,'
00998             // This is a special case to support also file formats directly written by
00999             // Inventor 2.1 classes.
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); // 7 = length of 'POINT ['
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); // allow to cancel
01013                 } else 
01014                     flag = false;
01015             } while (std::getline(rstrIn, line) && flag);
01016         }
01017         // read the point indices of the facets
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             // Get the next line and check for the index field which might begin
01024             // with the first index already.
01025             // This is a special case to support also file formats directly written by
01026             // Inventor 2.1 classes.
01027             // Furthermore we must check whether more than one triple is given per line, which
01028             // is handled in the while-loop.
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); // 12 = length of 'COORDINDEX ['
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                             // get a reference to the facet with defined normal
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); // allow to cancel
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         // insert the read-in vertex into a map to preserve the order
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         // insert the read-in triangle into a map to preserve the order
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         // insert the read-in quadrangle into a map to preserve the order
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     // Applying the nodes
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     // Converting data to Mesh. Negative conversion for right orientation of normal-vectors.
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     // make sure to add only vertices which are referenced by the triangles
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     // ask for write permission
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         // write file
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         // write file
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         // write file
01299         if (!SaveOBJ(str)) 
01300             throw Base::FileException("Export of OBJ mesh failed",FileName);
01301     }
01302     else if (fileformat == MeshIO::OFF) {
01303         // write file
01304         if (!SaveOFF(str)) 
01305             throw Base::FileException("Export of OFF mesh failed",FileName);
01306     }
01307     else if (fileformat == MeshIO::PLY) {
01308         // write file
01309         if (!SavePLY(str)) 
01310             throw Base::FileException("Export of PLY mesh failed",FileName);
01311     }
01312     else if (fileformat == MeshIO::IV) {
01313         // write file
01314         if (!SaveInventor(str))
01315             throw Base::FileException("Export of Inventor mesh failed",FileName);
01316     }
01317     else if (fileformat == MeshIO::PY) {
01318         // write file
01319         if (!SavePython(str))
01320             throw Base::FileException("Export of Python mesh failed",FileName);
01321     }
01322     else if (fileformat == MeshIO::VRML) {
01323         // write file
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         // Compressed VRML is nothing else than a GZIP'ped VRML ascii file
01330         // str.close();
01331         //Base::ogzstream gzip(FileName, std::ios::out | std::ios::binary);
01332         //FIXME: The compression level seems to be higher than with ogzstream
01333         //which leads to problems to load the wrz file in debug mode, the
01334         //application simply crashes.
01335         zipios::GZIPOutputStream gzip(str);
01336         // write file
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         // write file
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         // normal
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         // vertices
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);// allow to cancel
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 /*|| _rclMesh.CountFacets() == 0*/)
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         // normal
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         // vertices
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         // attribute 
01440         rstrOut.write((const char*)&usAtt, sizeof(usAtt));
01441 
01442         ++clIter;
01443         seq.next(true); // allow to cancel
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     // vertices
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); // allow to cancel
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); // allow to cancel
01473         }
01474     }
01475     // facet indices (no texture and normal indices)
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); // allow to cancel
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     // vertices
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); // allow to cancel
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); // allow to cancel
01513         }
01514     }
01515 
01516     // facet indices (no texture and normal indices)
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); // allow to cancel
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     // vertices
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     // facet indices (no texture and normal indices)
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     //  writer << writer.ind() << "<Mesh>" << std::endl;
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     // write the faces
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     // Header info
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     // write out the normals of the facets
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); // allow to cancel
01724     }
01725 
01726     rstrOut << " ]\n\n  }" << std::endl;
01727 
01728     // coordinates of the vertices
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); // allow to cancel
01747     }
01748 
01749     rstrOut << " ]\n\n  }" << std::endl;
01750 
01751     // and finally the facets with their point indices
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         // write two triples per line
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;   // reference to mesh data structure
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     // Write background
01933     // Note: We must write the background info straight after the header and before any geometry.
01934     // To see the background color in the Inventor viewer we must either skip the skyAngle property
01935     // or set it to 1.57, otherwise we'll see a strange beam in the scene.
01936     // FIXME: Test this also with external VRML viewer plugins.
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     // Transform
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     // write appearance
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) { // black
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; // end write appearance
02008 
02009 
02010     // write IndexedFaceSet
02011     rstrOut << "  geometry IndexedFaceSet\n  {\n";
02012     rstrOut << "    solid   FALSE\n";
02013 
02014     // write coords
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;  // end write coord
02035 
02036     rstrOut << "    colorPerVertex  " 
02037             << (bColorPerVertex ? "TRUE" : "FALSE") << std::endl;
02038 
02039     if (raclColor.size() > 0) {
02040         // write colors for each vertex
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     // write face index
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;  // End IndexedFaceSet
02080     rstrOut << "}" << std::endl;  // End Shape
02081 
02082     // close children and Transform
02083     rstrOut << "]\n}" << std::endl;
02084 
02085     // write viewpoints
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     // write navigation info
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     // write custom viewpoints
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     // save information about file
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     // annotationen
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     // write viewpoints
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         // build up the observer's coordinate system
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         // calc the view axis in world coordinates
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 for (int i = 0; i < _rclMesh.CountPoints(); i++)
02396 {
02397 unsigned short r =  (rand() * 255) / float(RAND_MAX);
02398 unsigned short g =  (rand() * 255) / float(RAND_MAX);
02399 unsigned short b =  (rand() * 255) / float(RAND_MAX);
02400 
02401   aclDummy.push_back(App::Color(r, g, b));
02402 }
02403 */
02404     return Save(rstrOut, aclDummy, rclMat, false);
02405 }
02406 

Generated on Wed Nov 23 19:00:23 2011 for FreeCAD by  doxygen 1.6.1