meshio.C

Go to the documentation of this file.
00001 
00008 #ifdef HAVE_CONFIG_H
00009 #include <tumble-conf.h>
00010 #endif /* HAVE_CONFIG_H */
00011 
00012 #include <fstream>
00013 #include <cstdio>
00014 
00015 #include "meshio.h"
00016 
00017 #include "beziermesh.h"
00018 #include "boundarymesh.h"
00019 #include "hash_map.h"
00020 #include "simulation.h"
00021 #include "spline.h"
00022 
00023 using namespace std;
00024 using namespace hashers;
00025 
00026 bool MeshInput::read(const char *filename) {
00027     char node_filename[ MAX_FILENAME ];
00028     char ele_filename[  MAX_FILENAME ];
00029     char edge_filename[ MAX_FILENAME ];
00030     char bdry_filename[ MAX_FILENAME ];
00031 
00032     bzero( node_filename, MAX_FILENAME );
00033     bzero( ele_filename,  MAX_FILENAME );
00034     bzero( edge_filename, MAX_FILENAME );
00035     bzero( bdry_filename, MAX_FILENAME );
00036 
00037     snprintf( node_filename, sizeof(node_filename), "%s.node", filename );
00038     snprintf( ele_filename,  sizeof(ele_filename),  "%s.ele",  filename );
00039     snprintf( edge_filename, sizeof(edge_filename), "%s.edge", filename );
00040     snprintf( bdry_filename, sizeof(bdry_filename), "%s.bdry", filename );
00041 
00042     node_file = fopen( node_filename, "r" );
00043     ele_file  = fopen( ele_filename, "r"  );
00044     edge_file = fopen( edge_filename, "r" );
00045     bdry_file = fopen( bdry_filename, "r" );
00046 
00047     if(!node_file) cout<<"MeshInput --- Error opening file: "<<node_filename<<endl;
00048     if(!ele_file)  cout<<"MeshInput --- Error opening file: "<< ele_filename<<endl;
00049     if(!edge_file) cout<<"MeshInput --- Error opening file: "<<edge_filename<<endl;
00050     if(!bdry_file) cout<<"MeshInput --- Error opening file: "<<bdry_filename<<endl;
00051 
00052     if( !node_file || !ele_file || !edge_file || !bdry_file ){
00053         if( fclose( node_file ) ) cout<<"Error closing node file!"<<endl;
00054         if( fclose( ele_file  ) ) cout<<"Error closing ele file!"<<endl;
00055         if( fclose( edge_file ) ) cout<<"Error closing edge file!"<<endl;
00056         if( fclose( bdry_file ) ) cout<<"Error closing bdry file!"<<endl;
00057         return false;
00058     }
00059 
00060     /* Step 1: read in node_file to the Node structure
00061      */
00062     vector<Node> nodes;
00063     char file_line[ MAX_FILE_LINE ];
00064     bzero( file_line, MAX_FILE_LINE );
00065 
00066     while ( fgets( file_line, MAX_FILE_LINE, node_file ) != NULL ) {
00067         nodes.push_back( Node( file_line ) );
00068     }
00069     //cout<<"Read "<<nodes.size()<<" Nodes"<<endl;
00070     /* Step 2: read BoundaryVertex's from bdry_file and add them to the
00071      * BoundaryMesh.  Only add CP's, we will add DP's later.
00072      */
00073     BoundaryVertexData bdry_vert_data;
00074     while ( read_boundary_vertex_data( &bdry_vert_data ) ) {
00075         bdry_verts[ bdry_vert_data.idx ] = bdry_mesh->add_boundary_vertex( nodes[ bdry_vert_data.node ].p );
00076     }
00077     //cout<<"Read "<<bdry_verts.size()<<" Boundary Vertexs"<<endl;
00078     /* Step 3: read in BoundaryEdge's from bdry_file.  Here we will only be adding the CP's.
00079      * The DP's will be added in later with the BezierEdge's.
00080      */
00081     BoundaryEdgeData bdry_edge_data;
00082     while ( read_boundary_edge_data( &bdry_edge_data ) ) {
00083         bdry_edges[ bdry_edge_data.idx ] = bdry_mesh->add_boundary_edge( bdry_verts[ bdry_edge_data.v0 ],
00084                                                                          bdry_verts[ bdry_edge_data.v1 ],
00085                                                                          bdry_edge_data.d,
00086                                                                          bdry_edge_data.k,
00087                                                                          (Movement)bdry_edge_data.fixed,
00088                                                                          bdry_edge_data.color,
00089                                                                          bdry_edge_data.restlength );
00090     }
00091     //cout<<"Read "<<bdry_edges.size()<<" Boundary Edges"<<endl;
00092     /* Step 4: Read in the BoundaryFace's and add them in */
00093     BoundaryFaceData bdry_face_data;
00094     bdry_faces[0] = NULL;
00095 
00096     while ( read_boundary_face_data( &bdry_face_data ) ) {
00097         bdry_faces[ bdry_face_data.idx ] = bdry_mesh->add_boundary_face( bdry_face_data.edges,
00098                                                                          bdry_face_data.min_angle,
00099                                                                          bdry_face_data.color );
00100     }
00101     //cout<<"Read "<<bdry_faces.size()<<" Boundary Faces"<<endl;
00102     /* Step 5: Read in the BezierEdge's from edge_file.  For each edge we will first consider
00103      * its vertexs.  If these coorespond to nodes in the node list that have not yet been added
00104      * then we will add the cooresponding BezierVertex along with its proper CP and DP.
00105      *
00106      * However there is an exception to be made in the case of BezierEdge's on the boundary.
00107      * Assuming the coorespoing nodes have not been added, we must perform a reverse lookup on the
00108      * cooresponding BoundaryEdge, via the u0 and u1 values.  This will give us a pointer to the CP.
00109      * we need to use this to hang the DP as we skiped that before.  Also we will need to hang data
00110      * off the internal point, whose CP was created by the QBSpline constructor in Step 3.
00111      *
00112      * Finally when all these points have been added or updated, we may add in the Edge.
00113      * Additionally, we must be sure to add all boundary edges BEFORE all non-boundary edges, thus we
00114      * keep a vector of the non-boundary edges and deal with them later.
00115      */
00116     BezierEdgeData edge_data;
00117     Node *node;
00118     vector<BezierEdgeData> internal_edges;
00119     ControlPoint cp0, cp1, cp2;
00120     int cp0_is_vert, cp2_is_vert;
00121     BoundaryEdge *be;
00122     BezierEdge *edge;
00123     BezierVertex *vert;
00124     while ( read_bezier_edge_data( &edge_data ) ) {
00125         if ( edge_data.is_bdry ) {
00126 
00127             be = bdry_edges[ edge_data.bdry ];
00128             if ( ! be->get_spline()->get_edge_cps( edge_data.u0, edge_data.u1, cp0, cp1, cp2, cp0_is_vert, cp2_is_vert ) ) {
00129                 printf( "Simulation::read_from_file  error, could not get edge cps from boundary mesh\n" );
00130                 return false;
00131             }
00132 
00133             node = &nodes[ edge_data.v0 ];
00134             if ( !node->added ) {
00135                 node->added = true;
00136                 vert = bezier_mesh->add_bezier_vertex( cp0, node->d );
00137                 bez_verts[ edge_data.v0 ] = vert;
00138                 if ( cp0_is_vert == 0 )
00139                     vert->set_bdry( be->get_vertex(0) );
00140                 else if ( cp0_is_vert == 1 )
00141                     vert->set_bdry( be->get_vertex(1) );
00142                 else
00143                     vert->set_bdry( be, edge_data.u0 );
00144             }
00145 
00146             node = &nodes[ edge_data.v2 ];
00147             if ( !node->added ) {
00148                 node->added = true;
00149                 vert = bezier_mesh->add_bezier_vertex( cp2, node->d );
00150                 bez_verts[ edge_data.v2 ] = vert;
00151                 if ( cp2_is_vert == 0 )
00152                     vert->set_bdry( be->get_vertex(0) );
00153                 else if ( cp2_is_vert == 1 )
00154                     vert->set_bdry( be->get_vertex(1) );
00155                 else
00156                     vert->set_bdry( be, edge_data.u1 );
00157             }
00158 
00159             node = &nodes[ edge_data.v1 ];
00160             node->added = true;
00161             edge = bezier_mesh->add_bezier_edge( cp1, node->d, bez_verts[ edge_data.v0 ], bez_verts[ edge_data.v2 ] );
00162             bez_edges[ edge_data.idx ] = edge;
00163             edge->set_bdry( be, edge_data.u0, edge_data.u1 );
00164         } else {
00165             internal_edges.push_back( edge_data );
00166         }
00167 
00168 
00169     }
00170     //cout<<"Read "<<bez_verts.size()<<" Bezier Vertexs"<<endl;
00171 
00172     /* Step 5b: Now add all internal edges */
00173     for ( vector<BezierEdgeData>::iterator i = internal_edges.begin(); i != internal_edges.end(); i++ ) {
00174 
00175         node = &nodes[ i->v0 ];
00176         if ( !node->added ) {
00177             bez_verts[ i->v0 ] = bezier_mesh->add_bezier_vertex( node->p, node->d );
00178             node->added = true;
00179         }
00180         node = &nodes[ i->v2 ];
00181         if ( !node->added ) {
00182             bez_verts[ i->v2 ] = bezier_mesh->add_bezier_vertex( node->p, node->d );
00183             node->added = true;
00184         }
00185         node = &nodes[ i->v1 ];
00186         bez_edges[ i->idx ] = bezier_mesh->add_bezier_edge( node->p, node->d, bez_verts[ i->v0 ], bez_verts[ i->v2 ] );
00187     }
00188     //cout<<"Read "<<bez_edges.size()<<" Bezier Edges"<<endl;
00189 
00190     /* Step 6: Read in the BezierTriangle's from ele_file.
00191      */
00192     BezierTriangleData tri_data;
00193     int num_bez_tris=0;
00194     while ( read_bezier_triangle_data( &tri_data ) ) {
00195         bezier_mesh->add_bezier_triangle( bdry_faces[ tri_data.bdry_face ], bez_edges[ tri_data.e0 ], bez_edges[ tri_data.e1 ], bez_edges[ tri_data.e2 ] );
00196         num_bez_tris++;
00197     }
00198     //cout<<"Read "<<num_bez_tris<<" Bezier Triangles"<<endl;
00199 
00200     if( fclose( node_file ) ) cout<<"Error closing node file!"<<endl;
00201     if( fclose( ele_file  ) ) cout<<"Error closing ele file!"<<endl;
00202     if( fclose( edge_file ) ) cout<<"Error closing edge file!"<<endl;
00203     if( fclose( bdry_file ) ) cout<<"Error closing bdry file!"<<endl;
00204 
00205     return true;
00206 }
00207 
00208 MeshInput::Node::Node( char *line ) {
00209     char * str;
00210     vector<double> data;
00211     added = FALSE;
00212     str = strtok( line, " \n" );
00213     num = atoi( str );
00214     str = strtok( NULL, " \n" );
00215     p.coords[ 0 ] = strtod( str, NULL );
00216     str = strtok( NULL, " \n" );
00217     p.coords[ 1 ] = strtod( str, NULL );
00218     str = strtok( NULL, " \n" );
00219     while ( str != NULL ) {
00220         data.push_back( strtod( str, NULL ) );
00221         str = strtok( NULL, " \n" );
00222     }
00223     d.update( data );
00224 }
00225 
00226 void MeshInput::Node::print() {
00227     cout << "Node: num: " << num << " added: " << added << " p: " << p << " d: " << d << endl;
00228 }
00229 
00230 int MeshInput::read_boundary_vertex_data( BoundaryVertexData *data ) {
00231     char str[ MAX_FILE_LINE ];
00232     char *temp;
00233     if ( ( fgets( str, MAX_FILE_LINE, bdry_file ) == NULL ) || !strncmp( str, "---", 3 ) ) {
00234         return FALSE;
00235     }
00236     temp = strtok( str, " \n" );
00237     data->idx = atoi( temp );
00238     temp = strtok( NULL, " \n" );
00239     data->node = atoi( temp );
00240     return TRUE;
00241 }
00242 
00243 int MeshInput::read_boundary_edge_data( BoundaryEdgeData *data ) {
00244     const int max_size = 10*MAX_FILE_LINE;
00245     char str[ max_size ];
00246     char *temp;
00247     int closed;
00248     int num;
00249     float f;
00250     Point2D d;
00251     char *ret;
00252 
00253     ret = fgets( str, max_size, bdry_file );
00254     if( (ret == NULL) || (strlen(str) >= max_size-2) ){
00255         cout<<"MeshInput::read_boundary_edge_data -- error reading first line or line too long"<<endl;
00256         return FALSE;
00257     }
00258     if ( !strncmp( str, "===", 3 ) ) {
00259         /* done with boundary edges */
00260         return FALSE;
00261     }
00262     num = sscanf( str, "%u %u %u %i %i %i %f", &data->idx, &data->v0, &data->v1, &closed, &data->fixed , &data->color, &f );
00263     if(num == 6)        data->restlength=0.0;
00264     else if(num == 7)   data->restlength=(double)f;
00265     else {
00266     printf("MeshInput::read_boundary_edge_data --- error reading spline data\n");
00267     exit(0);
00268     }
00269 
00270     closed ? data->closed = true : data->closed = false;
00271 
00272     data->d.clear();
00273     data->k.clear();
00274     /* Read in next line with d values */
00275     ret=fgets( str, max_size, bdry_file );
00276     if (( ret == NULL ) || (strlen(str)>= max_size-2)){
00277         cout<<"MeshInput::read_boundary_edge_data -- error reading second line or line too long"<<endl;
00278         return FALSE;
00279     }
00280 
00281     temp = strtok( str, " \n" );
00282     while ( temp != NULL ) {
00283         d.coords[ 0 ] = strtod( temp, NULL );
00284         temp = strtok( NULL, " \n" );
00285         d.coords[ 1 ] = strtod( temp, NULL );
00286         data->d.push_back( d );
00287         temp = strtok( NULL, " \n" );
00288     }
00289 
00290     /* Read in last line with k values */
00291     ret=fgets( str, max_size, bdry_file );
00292     if (( ret == NULL ) || (strlen(str) >= max_size-2)){
00293         cout<<"MeshInput::read_boundary_edge_data -- error reading third line or line too long"<<endl;
00294         return FALSE;
00295     }
00296 
00297     temp = strtok( str, " \n" );
00298     while ( temp != NULL ) {
00299         data->k.push_back( strtod( temp, NULL ) );
00300         temp = strtok( NULL, " \n" );
00301     }
00302     return TRUE;
00303 }
00304 
00305 int MeshInput::read_boundary_face_data( BoundaryFaceData *data ) {
00306     char str[ MAX_FILE_LINE ];
00307     char *temp;
00308 
00309     if ( fgets( str, MAX_FILE_LINE, bdry_file ) == NULL ) {
00310         return FALSE;
00311     }
00312     data->edges.clear();
00313     temp = strtok( str, " \n" );
00314     data->idx = atoi( temp );
00315     temp = strtok( NULL, " \n" );
00316     data->min_angle = strtod( temp, NULL );
00317     temp = strtok( NULL, " \n" );
00318     data->color = atoi( temp );
00319     while ( ( temp = strtok( NULL, " \n" ) ) != NULL ) {
00320         data->edges.push_back( bdry_edges[ atoi( temp ) ] );
00321     }
00322     return TRUE;
00323 }
00324 
00325 int MeshInput::read_bezier_edge_data( BezierEdgeData *data ) {
00326     char str[ MAX_FILE_LINE ];
00327     bzero( str, MAX_FILE_LINE );
00328     char *temp;
00329     if ( fgets( str, MAX_FILE_LINE, edge_file ) == NULL ) {
00330         return FALSE;
00331     }
00332     temp = strtok( str, " \n" );
00333     data->idx = atoi( temp );
00334     temp = strtok( NULL, " \n" );
00335     data->v0 = atoi( temp );
00336     temp = strtok( NULL, " \n" );
00337     data->v1 = atoi( temp );
00338     temp = strtok( NULL, " \n" );
00339     data->v2 = atoi( temp );
00340     temp = strtok( NULL, " \n" );
00341     data->bdry = atoi( temp );
00342     ( data->bdry < 0 ) ? data->is_bdry = false : data->is_bdry = true;
00343 
00344     if ( data->is_bdry ) {
00345         temp = strtok( NULL, " \n" );
00346         data->u0 = strtod( temp, NULL );
00347         temp = strtok( NULL, " \n" );
00348         data->u1 = strtod( temp, NULL );
00349     } else {
00350         data->u0 = 0.0;
00351         data->u1 = 0.0;
00352     }
00353     return TRUE;
00354 }
00355 
00356 int MeshInput::read_bezier_triangle_data( BezierTriangleData *data ) {
00357     char str[ MAX_FILE_LINE ];
00358     char *temp;
00359     int inverted;
00360     if ( fgets( str, MAX_FILE_LINE, ele_file ) == NULL ) {
00361         return FALSE;
00362     }
00363     temp = strtok( str, " \n" );
00364     data->idx = atoi( temp );
00365     temp = strtok( NULL, " \n" );
00366     data->e0 = atoi( temp );
00367     temp = strtok( NULL, " \n" );
00368     data->e1 = atoi( temp );
00369     temp = strtok( NULL, " \n" );
00370     data->e2 = atoi( temp );
00371     temp = strtok( NULL, " \n" );
00372     inverted = atoi( temp );
00373     inverted ? data->inverted = true : data->inverted = false;
00374     temp = strtok( NULL, " \n" );
00375     data->bdry_face = atoi( temp );
00376     return TRUE;
00377 }
00378 
00379 bool MeshOutput::write(const char *filename) {
00380     char node_filename[ MAX_FILENAME ];
00381     char ele_filename[ MAX_FILENAME ];
00382     char edge_filename[ MAX_FILENAME ];
00383     char bdry_filename[ MAX_FILENAME ];
00384 
00385     snprintf( node_filename, sizeof(node_filename), "%s.node", filename );
00386     snprintf( ele_filename,  sizeof(ele_filename),  "%s.ele",  filename );
00387     snprintf( edge_filename, sizeof(edge_filename), "%s.edge", filename );
00388     snprintf( bdry_filename, sizeof(bdry_filename), "%s.bdry", filename );
00389 
00390     node_file = fopen( node_filename, "w" );
00391     ele_file  = fopen( ele_filename, "w"  );
00392     edge_file = fopen( edge_filename, "w" );
00393     bdry_file = fopen( bdry_filename, "w" );
00394 
00395     if(!node_file) cout<<"MeshInput --- Error opening file: "<<node_filename<<endl;
00396     if(!ele_file)  cout<<"MeshInput --- Error opening file: "<< ele_filename<<endl;
00397     if(!edge_file) cout<<"MeshInput --- Error opening file: "<<edge_filename<<endl;
00398     if(!bdry_file) cout<<"MeshInput --- Error opening file: "<<bdry_filename<<endl;
00399 
00400     if(!node_file || !ele_file || !edge_file || !bdry_file){
00401         if( fclose( node_file ) ) cout<<"Error closing node file!"<<endl;
00402         if( fclose( ele_file  ) ) cout<<"Error closing ele file!"<<endl;
00403         if( fclose( edge_file ) ) cout<<"Error closing edge file!"<<endl;
00404         if( fclose( bdry_file ) ) cout<<"Error closing bdry file!"<<endl;
00405         return false;
00406     }
00407 
00408 
00409     /* These integers are used to assign an enumeration to control points and cells via
00410      *the hash_maps */
00411     unsigned node_index = 0;
00412     unsigned bez_edge_index = 0;
00413     unsigned bdry_vert_index = 0;
00414     unsigned bdry_edge_index = 0;
00415     unsigned bdry_face_index = 0;
00416 
00417     /* Step 1: dump all control points to node file.  This could be done by iterating
00418      * through the list of ControlPoints, however this will not let us determine
00419      * which data points are associated with each control point, therefore we
00420      * will iterate through the Bezier Vertexs.  I am assuming that BezierVertexs,
00421      * ControlPoints, and DataPoints are all in one-to-one coorespondence.
00422      */
00423     BezierMesh::Vertex_Hash_T::iterator viter;
00424     for(viter = bezier_mesh->get_vertices_begin();
00425         viter != bezier_mesh->get_vertices_end(); ++viter) {
00426         BezierVertex *v = *viter;
00427         node_hash[v->get_control_point()] = node_index++;
00428         node_to_file( v->get_control_point(), v->get_data_point() );
00429     }
00430 
00431     /* Step 2: dump all boundary vertexs to file*/
00432     BoundaryMesh::Vertex_Hash_T::iterator bviter;
00433     for(bviter = bdry_mesh->get_vertices_begin();
00434         bviter != bdry_mesh->get_vertices_end(); ++bviter ) {
00435         BoundaryVertex *bv = *bviter;
00436         bdry_vert_hash[ bv ] = bdry_vert_index++;
00437         bdry_vert_to_file( bv );
00438     }
00439     fprintf( bdry_file, "--- %u\n", bdry_vert_index );
00440 
00441     /* Step 3: dump all boundary edges to file*/
00442     BoundaryMesh::Edge_Hash_T::iterator beiter;
00443     for( beiter = bdry_mesh->get_edges_begin();
00444         beiter != bdry_mesh->get_edges_end(); ++beiter ) {
00445         BoundaryEdge *be = *beiter;
00446         bdry_edge_hash[ be ] = bdry_edge_index++;
00447         bdry_edge_to_file( be );
00448     }
00449     fprintf( bdry_file, "=== %u\n", bdry_edge_index );
00450 
00451     /* Step 4: dump all boundary faces to file*/
00452     BoundaryMesh::Face_Hash_T::iterator bfiter;
00453     for( bfiter = bdry_mesh->get_faces_begin();
00454         bfiter != bdry_mesh->get_faces_end(); ++bfiter ) {
00455         BoundaryFace *bf = *bfiter;
00456         bdry_face_hash[ bf ] = bdry_face_index++;
00457         bdry_face_to_file( bf );
00458     }
00459 
00460     /* Step 5: dump all bezier edges to file, but we also need to add thier
00461      *internal control point to the node file
00462      */
00463     BezierMesh::Edge_Hash_T::iterator eiter;
00464     for(eiter = bezier_mesh->get_edges_begin();
00465         eiter != bezier_mesh->get_edges_end(); ++eiter) {
00466         BezierEdge *e = *eiter;
00467         bez_edge_hash[ e ] = bez_edge_index++;
00468         node_hash[ e->get_control_point(1) ] = node_index++;
00469         node_to_file( e->get_control_point(1), e->get_data_point(1) );
00470         edge_to_file( e );
00471     }
00472 
00473     /* Step 6: dump all bezier triangles to file.  Here we do not need a hash because
00474      * these are the last to be added.  Instead the ele_to_file() function holds a static
00475      * integer index for the triangles to number them
00476      */
00477     BezierMesh::Face_Hash_T::iterator fiter;
00478     for(fiter = bezier_mesh->get_faces_begin();
00479         fiter != bezier_mesh->get_faces_end(); ++fiter ) {
00480         BezierTriangle *f = *fiter;
00481         ele_to_file( f, bezier_mesh);
00482     }
00483 
00484     if( fclose( node_file ) ) cout<<"Error closing node file!"<<endl;
00485     if( fclose( ele_file  ) ) cout<<"Error closing ele file!"<<endl;
00486     if( fclose( edge_file ) ) cout<<"Error closing edge file!"<<endl;
00487     if( fclose( bdry_file ) ) cout<<"Error closing bdry file!"<<endl;
00488     return true;
00489 }
00490 
00491 
00492 int MeshOutput::node_to_file( ControlPoint cp, DataPoint dp ) {
00493     fprintf( node_file, "%u %.12f %.12f", node_hash[ cp ], cp->coords[ 0 ], cp->coords[ 1 ] );
00494     for ( int i = 0; i < dp->length; i++ ) {
00495         fprintf( node_file, " %.12f", dp->fields[ i ] );
00496     }
00497     fprintf( node_file, "\n" );
00498     return TRUE;
00499 }
00500 
00501 int MeshOutput::edge_to_file( BezierEdge* edge ) {
00502     if ( ! edge->is_boundary() ) {
00503         fprintf( edge_file, "%u %u %u %u -1\n",
00504                  bez_edge_hash[ edge ],
00505                  node_hash[ edge->get_control_point(0) ],
00506                  node_hash[ edge->get_control_point(1) ],
00507                  node_hash[ edge->get_control_point(2) ] );
00508     } else {
00509         fprintf( edge_file, "%u %u %u %u %u %.12f %.12f\n",
00510                  bez_edge_hash[edge],
00511                  node_hash[ edge->get_control_point(0) ],
00512                  node_hash[ edge->get_control_point(1) ],
00513                  node_hash[ edge->get_control_point(2) ],
00514                  bdry_edge_hash[ edge->get_bdry_edge() ],
00515                  edge->get_u(0), edge->get_u(1) );
00516     }
00517     return TRUE;
00518 }
00519 
00520 int MeshOutput::ele_to_file( BezierTriangle* tri, BezierMesh *bezier_mesh ) {
00521     static unsigned tri_number = 0;
00522     fprintf( ele_file, "%u %u %u %u %u %u\n", tri_number++,
00523              bez_edge_hash[ tri->get_edge(0) ],
00524              bez_edge_hash[ tri->get_edge(1) ],
00525              bez_edge_hash[ tri->get_edge(2) ],
00526              tri->is_inverted( ) ,
00527              bdry_face_hash[ tri->get_bdry_face_or_null() ] );
00528     return TRUE;
00529 }
00530 
00531 int MeshOutput::bdry_vert_to_file( BoundaryVertex *vert ) {
00532     fprintf( bdry_file, "%u %u\n",
00533         bdry_vert_hash[ vert ], node_hash[ vert->get_control_point() ] );
00534     return TRUE;
00535 }
00536 
00537 int MeshOutput::bdry_edge_to_file( BoundaryEdge *edge ) {
00538     fprintf( bdry_file, "%u %u %u %u %u %u %.12f\n", bdry_edge_hash[ edge ],
00539              bdry_vert_hash[edge->get_vertex(0)],
00540              bdry_vert_hash[edge->get_vertex(1)],
00541              edge->get_spline()->closed, edge->get_fixed(), edge->get_color(),
00542              edge->get_spline()->restlength )
00543     ;
00544     int num_deboor = edge->get_spline()->get_num_deboor();
00545     ControlPoint d;
00546     unsigned i;
00547     for ( i=0; i < ( unsigned ) num_deboor; i++ ) {
00548         d = edge->get_spline()->get_deboor( i );
00549         fprintf( bdry_file, " %.12f %.12f", d->coords[ 0 ], d->coords[ 1 ] );
00550     }
00551     fprintf( bdry_file, "\n" );
00552     for ( i=0; i < edge->get_spline()->k.size(); i++ ) {
00553         fprintf( bdry_file, " %.12f", edge->get_spline()->k[ i ] );
00554     }
00555     fprintf( bdry_file, "\n" );
00556     return TRUE;
00557 }
00558 
00559 int MeshOutput::bdry_face_to_file( BoundaryFace *f ) {
00560     fprintf(bdry_file, "%u %.12f %u", bdry_face_hash[f],
00561             f->get_min_angle(), f->get_color() );
00562     for(BoundaryFace::edge_iterator it = f->begin_edges();
00563         it != f->end_edges(); ++it) {
00564       fprintf(bdry_file, " %u", bdry_edge_hash[*it]);
00565     }
00566     fprintf( bdry_file, "\n" );
00567     return TRUE;
00568 }
00569 
00570 static const char *official_header="Tumble Binary Geometry File";
00571 static const int official_header_len = 27;
00572 static const unsigned current_format_version=1;
00573 
00574 MeshBinaryInput::MeshBinaryInput(Simulation* _sim)
00575 {
00576     sim = _sim;
00577     bezier_mesh = sim->get_bezier_mesh();
00578     bdry_mesh = sim->get_boundary_mesh();
00579 }
00580 
00581 bool MeshBinaryInput::read(const char *filename)
00582 {
00583     if(!filename) return false;
00584     int len = strlen(filename);
00585     if( strncmp(filename+(len-4), ".geo", 4) ){
00586         cout<<"MeshBinaryInput -- filename:[ \""<<filename<<"\" ]  does not end in extension \".geo\""<<endl;
00587         return false;
00588     }
00589 
00590     ifstream in( filename, ios::binary | ios::in );
00591     if(!in){
00592         cout<<"MeshBinaryInput -- Cannot open file for input: "<<filename<<endl;
00593         return false;
00594     }
00595 
00596     struct Node {
00597         Point2D p;
00598         LinearData d;
00599     };
00600 
00601     hash_map<unsigned, BoundaryVertex*> bdry_verts;
00602     hash_map<unsigned, BoundaryEdge*> bdry_edges;
00603     hash_map<unsigned, BoundaryFace*> bdry_faces;
00604     hash_map<unsigned, BezierVertex*> bez_verts;
00605     hash_map<unsigned, BezierEdge*> bez_edges;
00606 
00607     unsigned num_nodes;
00608     unsigned num_bdry_verts;
00609     unsigned num_bdry_edges;
00610     unsigned num_bdry_faces;
00611     unsigned num_bez_verts;
00612     unsigned num_bez_edges;
00613     unsigned num_bez_tris;
00614 
00615     unsigned i,j;
00616     unsigned node_num;
00617     unsigned v0_idx;
00618     unsigned v1_idx;
00619     unsigned e0_idx, e1_idx, e2_idx;
00620     unsigned e_num;
00621     unsigned f_num;
00622     unsigned fixed;
00623     unsigned color;
00624 
00625     //read in and check header
00626     char header[official_header_len+1];
00627     bzero(header,official_header_len+1);
00628     in.read(header, official_header_len);
00629     if(strncmp(official_header, header, official_header_len)){
00630         cout<<"MeshBinaryInput --- error recieved bad header: "<<header<<endl;
00631         return false;
00632     }
00633 
00634     //read in and check version number
00635     unsigned vers_num;
00636     in.read((char*) & vers_num, sizeof(unsigned));
00637     if( vers_num != current_format_version ){
00638         cout<<"MeshBinaryInput --- Attempting to read a binary file of incorrect version."<<endl
00639             <<"Current version: "<<current_format_version<<" File version: "<<vers_num<<endl;
00640         return false;
00641     }
00642 
00643     //read in nodes
00644     //recall indexing starts at 1, so reflect that in node list
00645     in.read((char*) &num_nodes, sizeof(unsigned));
00646     //cout<<"Attempting to read in "<<num_nodes<<" nodes"<<endl;
00647     Node *nodes = new Node[num_nodes+1];
00648     double *data = NULL;
00649     unsigned this_data_size;
00650     unsigned data_size = 0;
00651     for(i=1; i<num_nodes+1; i++){
00652         in.read( (char*) &node_num, sizeof(unsigned));
00653         in.read( (char*) &nodes[i].p, sizeof(Point2D));
00654         in.read( (char*) &this_data_size, sizeof(unsigned));
00655         assert(node_num == i);
00656         //assert(this_data_size < 100);
00657         if(data==NULL) {
00658             data_size=this_data_size;
00659             data = new double[data_size];
00660         }
00661         assert(data_size == this_data_size);
00662         for(j=0; j<data_size; j++){
00663             in.read((char*) &data[j], sizeof(double));
00664         }
00665         nodes[i].d = LinearData(data, data_size);
00666     }
00667 
00668     //read in boundary vertexs
00669     in.read((char*) &num_bdry_verts, sizeof(unsigned));
00670     //cout<<"Attempting to read in "<<num_bdry_verts<<" BoundaryVertexs"<<endl;
00671     unsigned bdry_vert_idx;
00672     for(i=0; i<num_bdry_verts; i++){
00673         in.read((char*) &bdry_vert_idx, sizeof(unsigned));
00674         in.read((char*) &node_num, sizeof(unsigned));
00675         in.read((char*) &fixed, sizeof(unsigned));
00676         assert(bdry_vert_idx == i+1);
00677         assert(node_num != 0 && node_num <= num_nodes);
00678 
00679         //create new BoundaryVertex
00680         //fixed isn't used as we can figure this out later from the boundary edges
00681         bdry_verts[bdry_vert_idx] = bdry_mesh->add_boundary_vertex( nodes[node_num].p );
00682     }
00683 
00684     //read in boundary edges
00685     in.read((char*) &num_bdry_edges, sizeof(unsigned));
00686     //cout<<"Attempting to read in "<<num_bdry_edges<<" BoundaryEdges"<<endl;
00687     unsigned bdry_edge_idx;
00688     unsigned num_internal_deboor;
00689     unsigned num_knots;
00690     double restlength;
00691     vector<Point2D> deboor;
00692     vector<double> knots;
00693     double kval;
00694     for(i=0; i<num_bdry_edges; i++){
00695         in.read((char*) &bdry_edge_idx, sizeof(unsigned));
00696         in.read((char*) &v0_idx, sizeof(unsigned));
00697         in.read((char*) &v1_idx, sizeof(unsigned));
00698         in.read((char*) &fixed, sizeof(unsigned));
00699         in.read((char*) &color, sizeof(unsigned));
00700         in.read((char*) &restlength, sizeof(double));
00701 
00702         assert(bdry_edge_idx == i+1);
00703         assert(v0_idx != 0 && v0_idx <= num_bdry_verts);
00704         assert(v1_idx != 0 && v1_idx <= num_bdry_verts);
00705         assert(restlength >= 0.0 );
00706 
00707         //read in deboor points
00708         //must add endpoints as well
00709         in.read((char*) &num_internal_deboor, sizeof(unsigned));
00710         deboor.clear();
00711         deboor.push_back(bdry_verts[v0_idx]->get_cp());
00712         for(j=0; j<num_internal_deboor; j++){
00713             in.read((char*) &node_num, sizeof(unsigned));
00714             deboor.push_back(nodes[node_num].p);
00715         }
00716         deboor.push_back(bdry_verts[v1_idx]->get_cp());
00717 
00718         //read in knot values
00719         knots.clear();
00720         in.read((char*) &num_knots, sizeof(unsigned));
00721         for(j=0; j<num_knots;j++){
00722             in.read((char*) &kval, sizeof(double));
00723             knots.push_back(kval);
00724         }
00725         assert(num_knots-1 == num_internal_deboor);
00726         assert(num_knots == deboor.size()-1);
00727 
00728         //create new BoundaryEdge
00729         bdry_edges[bdry_edge_idx] = bdry_mesh->add_boundary_edge( bdry_verts[v0_idx], bdry_verts[v1_idx],
00730                                                                   deboor, knots, (Movement)fixed, color, restlength);
00731     }
00732 
00733     // read in boundary faces
00734     in.read((char*) &num_bdry_faces, sizeof(unsigned));
00735     //cout<<"Attempting to read in "<<num_bdry_faces<<" BoundaryFaces"<<endl;
00736     unsigned bdry_face_idx;
00737     double min_angle;
00738     unsigned num_edges;
00739     vector<BoundaryEdge*> face_edges;
00740     for(i=0; i<num_bdry_faces; i++){
00741         in.read((char*) &bdry_face_idx, sizeof(unsigned));
00742         in.read((char*) &min_angle, sizeof(double));
00743         in.read((char*) &color, sizeof(unsigned));
00744         in.read((char*) &num_edges, sizeof(unsigned));
00745         assert(bdry_face_idx == i+1);
00746         assert(min_angle >= 0.0);
00747         assert(num_edges >= 1);
00748 
00749         face_edges.clear();
00750         for(j=0; j < num_edges; j++){
00751             in.read((char*) &e_num, sizeof(unsigned));
00752             face_edges.push_back( bdry_edges[e_num] );
00753         }
00754 
00755         bdry_faces[bdry_face_idx] = bdry_mesh->add_boundary_face( face_edges, min_angle, color);
00756     }
00757 
00758     //read in bezier vertexs
00759     in.read((char*) &num_bez_verts, sizeof(unsigned));
00760     //cout<<"Attempting to read in "<<num_bez_verts<<" BezierVertexs"<<endl;
00761     unsigned bez_vert_idx;
00762     unsigned bdry_type;
00763     unsigned bdry_idx;
00764     unsigned bdry_knot_idx;
00765     QBSpline *spline;
00766     BezierVertex *v;
00767     BoundaryVertex *bv;
00768     BoundaryEdge *be;
00769     for(i=0; i<num_bez_verts; i++){
00770         in.read((char*) &bez_vert_idx,  sizeof(unsigned));
00771         in.read((char*) &node_num,      sizeof(unsigned));
00772         in.read((char*) &bdry_type,     sizeof(unsigned));
00773         in.read((char*) &bdry_idx,      sizeof(unsigned));
00774         in.read((char*) &bdry_knot_idx, sizeof(unsigned));
00775 
00776         assert(bez_vert_idx == i+1);
00777         assert(node_num != 0 && node_num <= num_nodes);
00778         assert(bdry_type <= 2);
00779 
00780         if(bdry_type == 0){
00781             //d2 - internal vertex - no bdry to worry about
00782             assert(bdry_idx == 0);
00783             assert(bdry_knot_idx == 0);
00784             bez_verts[bez_vert_idx] = bezier_mesh->add_bezier_vertex( nodes[node_num].p, nodes[node_num].d );
00785         } else if(bdry_type==1){
00786             //d0 vertex - need to get CP from vertex and set bdry
00787             assert(bdry_idx != 0 && bdry_idx <= num_bdry_verts);
00788             assert(bdry_knot_idx == 0);
00789             bv=bdry_verts[bdry_idx];
00790             v = bezier_mesh->add_bezier_vertex( bv->get_control_point(),
00791                 nodes[node_num].d );
00792             bez_verts[bez_vert_idx] = v;
00793             v->set_bdry(bv);
00794         } else{
00795             //d1 vertex - need to get CP from bdry edge with given knot idx and set bdry
00796             assert(bdry_idx != 0 && bdry_idx <= num_bdry_edges);
00797             assert(bdry_knot_idx != 0);
00798             be = bdry_edges[bdry_idx];
00799             spline = be->get_spline();
00800             v = bezier_mesh->add_bezier_vertex( spline->get_control_point_at_idx(bdry_knot_idx), nodes[node_num].d );
00801             bez_verts[bez_vert_idx] = v;
00802             v->set_bdry(be,(int)bdry_knot_idx);
00803         }
00804     }
00805 
00806     //read in bezier edges
00807     in.read((char*) &num_bez_edges, sizeof(unsigned));
00808     //cout<<"Attempting to read in "<<num_bez_edges<<" BezierEdges"<<endl;
00809     unsigned bez_edge_idx;
00810     BezierEdge *e;
00811     unsigned bdry_knot_idx0, bdry_knot_idx1;
00812     for(i=0; i<num_bez_edges; i++){
00813         in.read((char*) &bez_edge_idx,   sizeof(unsigned));
00814         in.read((char*) &v0_idx,         sizeof(unsigned));
00815         in.read((char*) &v1_idx,         sizeof(unsigned));
00816         in.read((char*) &node_num,       sizeof(unsigned));
00817         in.read((char*) &bdry_idx,       sizeof(unsigned));
00818         in.read((char*) &bdry_knot_idx0, sizeof(unsigned));
00819         in.read((char*) &bdry_knot_idx1, sizeof(unsigned));
00820 
00821         assert(bez_edge_idx == i+1);
00822         assert(v0_idx != 0 && v0_idx <= num_bez_verts);
00823         assert(v1_idx != 0 && v0_idx <= num_bez_verts);
00824         assert(node_num != 0 && node_num <= num_nodes);
00825 
00826         if(bdry_idx == 0){
00827             //not a bdry edge
00828             assert(bdry_knot_idx0 == 0);
00829             assert(bdry_knot_idx1 == 0);
00830             bez_edges[bez_edge_idx] = bezier_mesh->add_bezier_edge( nodes[node_num].p, nodes[node_num].d, bez_verts[v0_idx], bez_verts[v1_idx] );
00831         } else {
00832             //is a bdry edges, get node cp from spline, set bdry
00833             assert(bdry_idx <= num_bdry_edges);
00834             be = bdry_edges[bdry_idx];
00835             spline = be->get_spline();
00836             assert( abs((int)bdry_knot_idx0 - (int)bdry_knot_idx1) == 1 );
00837             e = bezier_mesh->add_bezier_edge( spline->get_edge_center_cp(bdry_knot_idx0, bdry_knot_idx1),
00838                                               nodes[node_num].d, bez_verts[v0_idx], bez_verts[v1_idx] );
00839             bez_edges[bez_edge_idx] = e;
00840             e->set_bdry(be, spline->get_u_at_idx(bdry_knot_idx0), spline->get_u_at_idx(bdry_knot_idx1));
00841         }
00842     }
00843 
00844     //read in bezier faces
00845     in.read((char*) &num_bez_tris, sizeof(unsigned));
00846     //cout<<"Attempting to read in "<<num_bez_tris<<" BezierTriangles"<<endl;
00847     for(i=0; i<num_bez_tris; i++){
00848         in.read((char*) &e0_idx, sizeof(unsigned));
00849         in.read((char*) &e1_idx, sizeof(unsigned));
00850         in.read((char*) &e2_idx, sizeof(unsigned));
00851     bool ihf; // Inverse-Handed-Face Flag  // tp517: 4/16/07
00852     in.read((char*) &ihf, sizeof(bool));
00853         in.read((char*) &f_num, sizeof(unsigned));
00854 
00855         assert(e0_idx != 0 && e0_idx <= num_bez_edges);
00856         assert(e1_idx != 0 && e1_idx <= num_bez_edges);
00857         assert(e2_idx != 0 && e2_idx <= num_bez_edges);
00858         /* f_num zero is the null face, so it's allowed */
00859         assert(f_num <= num_bdry_faces);
00860 
00861         bezier_mesh->add_bezier_triangle(bdry_faces[f_num], bez_edges[e0_idx], bez_edges[e1_idx], bez_edges[e2_idx],ihf); // read/write ihf: tp517 4/16/07
00862     }
00863 
00864     return true;
00865 }
00866 
00867 MeshBinaryOutput::MeshBinaryOutput(Simulation* _sim)
00868 {
00869     sim = _sim;
00870     bezier_mesh = sim->get_bezier_mesh();
00871     bdry_mesh = sim->get_boundary_mesh();
00872 }
00873 
00874 MeshBinaryOutput::MeshBinaryOutput(BezierMesh *_bezier_mesh, BoundaryMesh *_bdry_mesh)
00875 {
00876     sim = NULL;
00877     bezier_mesh = _bezier_mesh;
00878     bdry_mesh = _bdry_mesh;
00879 }
00880 
00881 bool MeshBinaryOutput::write(const char *filename)
00882 {
00883     if(!filename) return false;
00884     int len = strlen(filename);
00885     if( strncmp(filename+(len-4), ".geo", 4) ){
00886         cout<<"MeshBinaryOutput -- filename:[ \""<<filename<<"\" ]  does not end in extension \".geo\""<<endl;
00887         return false;
00888     }
00889 
00890     ofstream out( filename, ios::binary | ios::out | ios::trunc );
00891     if(!out){
00892         cout<<"MeshBinaryOutput -- Cannot open file for output: "<<filename<<endl;
00893         return false;
00894     }
00895 
00896     /* write header and version number */
00897     out.write( official_header, official_header_len);
00898     out.write((const char *) &current_format_version, sizeof(unsigned));
00899 
00900     //iterators for cells
00901     BezierMesh::Vertex_Hash_T::const_iterator bez_v_it;
00902     BezierMesh::Edge_Hash_T::const_iterator bez_e_it;
00903     BezierMesh::Face_Hash_T::const_iterator bez_t_it;
00904     BoundaryMesh::Vertex_Hash_T::const_iterator bdry_v_it;
00905     BoundaryMesh::Edge_Hash_T::const_iterator bdry_e_it;
00906     BoundaryMesh::Face_Hash_T::const_iterator bdry_f_it;
00907 
00908     //mappings from cells to thier indexes
00909     hash_map<ControlPoint, unsigned, ControlPointHasher> node_idx;
00910     hash_map<BezierVertex*, unsigned> bezvert_idx;
00911     hash_map<BezierEdge*, unsigned> bezedge_idx;
00912     hash_map<BoundaryVertex*, unsigned> bdryvert_idx;
00913     hash_map<BoundaryEdge*, unsigned> bdryedge_idx;
00914     hash_map<BoundaryFace*, unsigned> bdryface_idx;
00915 
00916     //counters
00917     // we will start all indexing at 1, to provide 0 as a free variable with no meaning for special cases
00918     unsigned nodes_ctr = 1;
00919     unsigned bezverts_ctr = 1;
00920     unsigned bezedges_ctr = 1;
00921     unsigned beztris_ctr = 1;
00922     unsigned bdryverts_ctr = 1;
00923     unsigned bdryedges_ctr = 1;
00924     unsigned bdryfaces_ctr = 1;
00925 
00926     ControlPoint cp;
00927     DataPoint dp;
00928     unsigned data_len;
00929     unsigned node_num;
00930     unsigned v_num;
00931     unsigned e_num;
00932     unsigned f_num;
00933     unsigned num_edges;
00934     unsigned fixed;
00935     unsigned color;
00936     unsigned i;
00937 
00938     /* write data nodes.  These are all the data points and thier coordinates
00939      * there is one for every vertex and one for the middle cp of every edge
00940      */
00941     unsigned total_num_nodes = bezier_mesh->get_num_vertices()
00942                              + bezier_mesh->get_num_edges();
00943     out.write((char*) &total_num_nodes, sizeof(total_num_nodes));
00944     //bezier vert nodes
00945     for(bez_v_it = bezier_mesh->get_vertices_begin();
00946         bez_v_it != bezier_mesh->get_vertices_end(); ++bez_v_it){
00947         const BezierVertex *v = *bez_v_it;
00948         ControlPoint cp = v->get_control_point();
00949         node_idx[ cp ] = nodes_ctr;
00950         out.write((const char*) &nodes_ctr, sizeof(nodes_ctr));
00951         Point2D p = v->get_cp();
00952         out.write((const char*) &p, sizeof(p));
00953         DataPoint dp = v->get_data_point();
00954         data_len = dp->length;
00955         out.write((const char*) &data_len, sizeof(data_len));
00956         out.write((const char*) dp->fields, data_len * sizeof(*dp->fields));
00957         nodes_ctr++;
00958     }
00959     //bezier edge nodes
00960     for(bez_e_it = bezier_mesh->get_edges_begin();
00961         bez_e_it != bezier_mesh->get_edges_end(); ++bez_e_it){
00962         const BezierEdge *e = *bez_e_it;
00963         node_idx[e->get_control_point(1)] = nodes_ctr;
00964         out.write( (const char*) &nodes_ctr, sizeof(nodes_ctr));
00965         out.write( (const char*) &(e->get_cp(1).coords), sizeof(Point2D));
00966         const LinearData& data = e->get_dp(1);
00967         unsigned data_len = data.length;
00968         out.write( (const char*) &data_len, sizeof(data_len));
00969         out.write( (const char*) data.fields, data_len * sizeof(*data.fields));
00970         nodes_ctr++;
00971     }
00972     //cout<<"Wrote "<<nodes_ctr-1<<" nodes to binary file"<<endl;
00973 
00974     /* Write Boundary Vertexs */
00975     unsigned total_num_bdry_verts = bdry_mesh->get_num_vertices();
00976     out.write((char*) &total_num_bdry_verts, sizeof(total_num_bdry_verts));
00977 
00978     for(bdry_v_it = bdry_mesh->get_vertices_begin();
00979         bdry_v_it != bdry_mesh->get_vertices_end(); ++bdry_v_it) {
00980         BoundaryVertex *bdry_v = *bdry_v_it;
00981         bdryvert_idx[ bdry_v ] = bdryverts_ctr;
00982 
00983         //write idx
00984         out.write( (const char*) &bdryverts_ctr, sizeof(bdryverts_ctr));
00985 
00986         //write node idx
00987         node_num = node_idx[ bdry_v->get_control_point() ];
00988         out.write( (const char*) &node_num, sizeof(node_num));
00989 
00990         //write fixed
00991         fixed = bdry_v->get_fixed();
00992         out.write( (const char*) &fixed, sizeof(fixed));
00993 
00994         bdryverts_ctr++;
00995     }
00996     //cout<<"Wrote "<<bdryverts_ctr-1<<" BoundaryVertexs to binary file"<<endl;
00997 
00998     /* Write Boundary Edges */
00999     unsigned total_num_bdry_edges = bdry_mesh->get_num_edges();
01000     out.write((char*) &total_num_bdry_edges, sizeof(total_num_bdry_edges));
01001 
01002     for(bdry_e_it = bdry_mesh->get_edges_begin();
01003         bdry_e_it != bdry_mesh->get_edges_end(); ++bdry_e_it){
01004         BoundaryEdge *bdry_e = *bdry_e_it;
01005         QBSpline *spline;
01006         unsigned num_internal_deboor, num_knots;
01007         double knot_val;
01008         double restlength;
01009 
01010         bdryedge_idx[ bdry_e ] = bdryedges_ctr;
01011 
01012         //write bdry edge index
01013         out.write( (const char*) &bdryedges_ctr, sizeof(unsigned));
01014 
01015         //write first endpoint
01016         v_num = bdryvert_idx[ bdry_e->get_vertex(0) ];
01017         out.write( (const char*) &v_num, sizeof(unsigned));
01018 
01019         //write second endpoint
01020         v_num = bdryvert_idx[ bdry_e->get_vertex(1) ];
01021         out.write( (const char*) &v_num, sizeof(unsigned));
01022 
01023         //write fixed and color
01024         spline = bdry_e->get_spline();
01025         fixed = bdry_e->get_fixed();
01026         color = bdry_e->get_color();
01027         restlength = spline->restlength;
01028         out.write( (const char*) &fixed, sizeof(fixed));
01029         out.write( (const char*) &color, sizeof(color));
01030         out.write( (const char*) &restlength, sizeof(restlength));
01031 
01032 
01033         //write the internal deboor point node numbers
01034         //since we already have the endpoints recorded, there is no reason to
01035         //write them again.  This assumption is violated during the construction
01036         // of the mesh using the conformal mesher, but we don't care enough to
01037         // deal with that case: the boundary edges will look like they all have
01038         // a control point at the origin.
01039         num_internal_deboor = spline->get_num_deboor()-2;
01040         out.write( (const char*) &num_internal_deboor, sizeof(unsigned));
01041         for(i=0; i < num_internal_deboor; i++){
01042             node_num = node_idx[ spline->get_deboor(i+1) ];
01043             out.write( (const char*) &node_num, sizeof(unsigned));
01044         }
01045 
01046         //write num_knots and knot values
01047         num_knots = spline->k.size();
01048         out.write( (const char*) &num_knots, sizeof(unsigned));
01049         for(i=0; i < num_knots; i++){
01050             knot_val = spline->k[i];
01051             out.write( (const char*) &knot_val, sizeof(double));
01052         }
01053 
01054         bdryedges_ctr++;
01055     }
01056     //cout<<"Wrote "<<bdryedges_ctr-1<<" BoundaryEdges to binary file"<<endl;
01057 
01058 
01059     /* Write Boundary Faces */
01060     unsigned total_num_bdry_faces = bdry_mesh->get_num_faces();
01061     out.write((char*) &total_num_bdry_faces, sizeof(total_num_bdry_faces));
01062 
01063     /* Index zero is the null face. */
01064     bdryface_idx[ NULL ] = 0;
01065     bdryfaces_ctr = 1;
01066 
01067     for(bdry_f_it = bdry_mesh->get_faces_begin();
01068         bdry_f_it != bdry_mesh->get_faces_end(); ++bdry_f_it){
01069         BoundaryFace *bdry_f = *bdry_f_it;
01070         bdryface_idx[ bdry_f ] = bdryfaces_ctr;
01071 
01072         //write index
01073         out.write( (const char*) &bdryfaces_ctr, sizeof(unsigned));
01074 
01075         //write min_angle
01076         double min_angle = bdry_f->get_min_angle();
01077         out.write( (const char*) &min_angle, sizeof(double));
01078 
01079         //write color
01080         unsigned color = bdry_f->get_color();
01081         out.write( (const char*) &color, sizeof(color));
01082 
01083         //write edge idxs
01084         num_edges = bdry_f->num_edges();
01085         out.write( (const char*) &num_edges, sizeof(unsigned));
01086         for(BoundaryFace::edge_iterator it = bdry_f->begin_edges();
01087             it != bdry_f->end_edges(); ++it) {
01088           unsigned e = bdryedge_idx[ *it ];
01089           out.write( (const char*) &e, sizeof(e));
01090         }
01091 
01092         bdryfaces_ctr++;
01093     }
01094     //cout<<"Wrote "<<bdryfaces_ctr-1<<" BoundaryFaces to binary file"<<endl;
01095 
01096 
01097     /* Write Bezier Vertexs */
01098     unsigned total_num_bez_verts = bezier_mesh->get_num_vertices();
01099     out.write((char*) &total_num_bez_verts, sizeof(total_num_bez_verts));
01100 
01101     for(bez_v_it = bezier_mesh->get_vertices_begin();
01102         bez_v_it != bezier_mesh->get_vertices_end(); ++bez_v_it){
01103         BezierVertex *bez_v = *bez_v_it;
01104         unsigned bdry_type;
01105         unsigned bdry_idx;
01106         unsigned bdry_edge_knot_idx;
01107 
01108         bezvert_idx[ bez_v ] = bezverts_ctr;
01109         //write bezier vertex idx
01110         out.write( (const char*) &bezverts_ctr, sizeof(unsigned));
01111 
01112         //write node idx
01113         node_num = node_idx[ bez_v->get_control_point() ];
01114         out.write( (const char*) &node_num, sizeof(unsigned));
01115 
01116         //write bdry type (0=none, 1=bdry vertex, 2=bdry edge)
01117         //write bdry idx (depends on bdry_type)
01118         //write bdry knot idx
01119         // Who knows what possessed Mark to use that setting of 0/1/2;
01120         // now I translate from the containment dimension, to maintain
01121         // binary compatibility.
01122         switch(bez_v->containment_dimension()) {
01123           case 0:
01124             bdry_type = 1;
01125             bdry_idx= bdryvert_idx[ bez_v->get_bdry_vertex() ];
01126             bdry_edge_knot_idx=0;
01127             break;
01128           case 1:
01129             bdry_type = 2;
01130             bdry_idx = bdryedge_idx[ bez_v->get_bdry_edge() ];
01131             bdry_edge_knot_idx =
01132               bez_v->get_bdry_edge()->get_spline()->get_bezier_vertex_idx(bez_v);
01133             assert(bdry_edge_knot_idx > 0); //this index cannot be endpoints
01134             break;
01135           case 2:
01136             bdry_type = 0;
01137             bdry_idx=0;
01138             bdry_edge_knot_idx=0;
01139             break;
01140           default: assert(0);
01141         }
01142         out.write( (const char*) &bdry_type, sizeof(bdry_type));
01143         out.write( (const char*) &bdry_idx, sizeof(unsigned));
01144         out.write( (const char*) &bdry_edge_knot_idx, sizeof(unsigned));
01145 
01146         bezverts_ctr++;
01147     }
01148     //cout<<"Wrote "<<bezverts_ctr-1<<" BezierVertexs to binary file"<<endl;
01149 
01150 
01151     /* Write Bezier Edges */
01152     unsigned total_num_bez_edges = bezier_mesh->get_num_edges();
01153     out.write((char*) &total_num_bez_edges, sizeof(total_num_bez_edges));
01154 
01155     for(bez_e_it = bezier_mesh->get_edges_begin();
01156         bez_e_it != bezier_mesh->get_edges_end(); ++bez_e_it){
01157         BezierEdge *bez_e = *bez_e_it;
01158         unsigned bdry_e_num, bdry_u0_idx, bdry_u1_idx;
01159         BezierVertex *v0, *v1;
01160         bool orientation;
01161         unsigned last_idx;
01162         bezedge_idx[ bez_e ] = bezedges_ctr;
01163 
01164         //write bezier edge idx
01165         out.write( (const char*) &bezedges_ctr, sizeof(unsigned));
01166 
01167         //write endpoint idxs
01168         v_num = bezvert_idx[ bez_e->get_vertex(0) ];
01169         out.write( (const char*) &v_num, sizeof(unsigned));
01170         v_num = bezvert_idx[ bez_e->get_vertex(1) ];
01171         out.write( (const char*) &v_num, sizeof(unsigned));
01172 
01173         //write node idx
01174         node_num = node_idx[ bez_e->get_control_point(1) ];
01175         out.write( (const char*) &node_num, sizeof(unsigned));
01176 
01177         //write bdry edge idx, (0 if not on bdry)
01178         if(bez_e->is_boundary()) {
01179             BoundaryEdge *bdry_e = bez_e->get_bdry_edge();
01180             bdry_e_num = bdryedge_idx[ bdry_e ];
01181             v0 = bez_e->get_vertex(0);
01182             v1 = bez_e->get_vertex(1);
01183 
01184             /* This will get the knot index if the vertex is a D1*/
01185             bdry_u0_idx = bdry_e->get_spline()->get_bezier_vertex_idx( v0 );
01186             bdry_u1_idx = bdry_e->get_spline()->get_bezier_vertex_idx( v1 );
01187 
01188             /* Otherwise the vertex is a D0 vertex (a endpoint of the spline)
01189              * so find it's knot index with respect to the endpoints of the Boundary Edge
01190              * again we avoid comparison of floating-points that would otherwise be necessary
01191              */
01192 
01193             /* determine how spline is parameterized with respecet to the endpoints of the bdry edge
01194              * if the first vertex of the bdry edge cooresponds to the begining of the parameterization
01195              * then orientation is true
01196              */
01197             QBSpline *spline = bdry_e->get_spline();
01198             orientation = (spline->b[0] == bdry_e->get_vertex(0)->get_control_point());
01199             last_idx = spline->k.size()-1;
01200 
01201             //just a check.  if both of bezier edge's vertexs are endpoints of spline, then spline must be short
01202             if(bdry_u0_idx ==0 && bdry_u1_idx==0){
01203                 assert(spline->k.size()==2);
01204                 assert(!spline->closed);
01205             }
01206 
01207             //if bezier edge's first vertex is endpoint, then find it's knot idx
01208             if(bdry_u0_idx == 0){
01209                 if(spline->closed){
01210                     if(bdry_u1_idx-1 == 0) bdry_u0_idx=0;
01211                     else bdry_u0_idx=last_idx;
01212                 } else {
01213                     if( v0 == bdry_e->get_vertex(0)->get_bezier())
01214                         bdry_u0_idx = (orientation) ? 0 : last_idx;
01215                     else if( v0 == bdry_e->get_vertex(1)->get_bezier())
01216                         bdry_u0_idx = (orientation) ? last_idx : 0;
01217                 }
01218             }
01219 
01220             //if bezier edge's second vertex is endpoint, then find it's knot idx
01221             if(bdry_u1_idx == 0){
01222                 if(spline->closed){
01223                     if(bdry_u0_idx-1 == 0) bdry_u1_idx=0;
01224                     else bdry_u1_idx=last_idx;
01225                 } else{
01226                     if( v1 == bdry_e->get_vertex(0)->get_bezier())
01227                         bdry_u1_idx = (orientation) ? 0 : last_idx;
01228                     else if( v1 == bdry_e->get_vertex(1)->get_bezier())
01229                         bdry_u1_idx = (orientation) ? last_idx : 0;
01230                 }
01231             }
01232             //cout<<"orientation: "<<orientation<<" u0_idx:"<<bdry_u0_idx<<" u1_idx:"<<bdry_u1_idx<<" last_idx:"<<last_idx<<endl;
01233             assert( abs((int)bdry_u0_idx - (int)bdry_u1_idx) == 1);
01234 
01235         } else {
01236             bdry_e_num = 0;
01237             bdry_u0_idx = 0;
01238             bdry_u1_idx = 0;
01239         }
01240 
01241         out.write( (const char*) &bdry_e_num,  sizeof(unsigned));
01242         out.write( (const char*) &bdry_u0_idx, sizeof(unsigned));
01243         out.write( (const char*) &bdry_u1_idx, sizeof(unsigned));
01244 
01245         bezedges_ctr++;
01246     }
01247     //cout<<"[MeshIO.C] Wrote "<<bezedges_ctr-1<<" BezierEdges to binary file"<<endl;
01248 
01249     /* Write Bezier Triangles */
01250     unsigned total_num_bez_tris = bezier_mesh->get_num_faces();
01251     out.write((char*) &total_num_bez_tris, sizeof(total_num_bez_tris));
01252 
01253 
01254     //cout << "[MeshIO.C] Writing bezier triangles"<<endl;
01255     for(bez_t_it = bezier_mesh->get_faces_begin();
01256         bez_t_it != bezier_mesh->get_faces_end(); ++bez_t_it){
01257         BezierTriangle *bez_t = *bez_t_it;
01258 
01259         //write edge idxs
01260         e_num = bezedge_idx[ bez_t->get_edge(0) ];
01261         out.write( (const char*) &e_num, sizeof(unsigned));
01262         e_num = bezedge_idx[ bez_t->get_edge(1) ];
01263         out.write( (const char*) &e_num, sizeof(unsigned));
01264         e_num = bezedge_idx[ bez_t->get_edge(2) ];
01265         out.write( (const char*) &e_num, sizeof(unsigned));
01266 
01267     //write inverse_handed_flag, tp517:4/16/07
01268     bool ihf = bezier_mesh->is_inverse_handed(bez_t);
01269     out.write( (const char*) &ihf, sizeof(bool));
01270 
01271         //write bdry face
01272         f_num = bdryface_idx[ bez_t->get_bdry_face_or_null() ];
01273         out.write( (const char*) &f_num, sizeof(unsigned));
01274 
01275         beztris_ctr++;
01276     }
01277     //cout<<"Wrote "<<beztris_ctr-1<<" BezierTriangles to binary file"<<endl;
01278 
01279     out.close();
01280 
01281     return true;
01282 }
01283 
01284 bool MeshBinaryOutput::write(const char *filename, BezierMesh *bez,
01285                              BoundaryMesh *bdry)
01286 {
01287   MeshBinaryOutput mo(bez,bdry);
01288   return mo.write(filename);
01289 }
01290 
01291 bool MeshBinaryOutput::write(const char *filename, Simulation *sim)
01292 {
01293   MeshBinaryOutput mo(sim);
01294   return mo.write(filename);
01295 }

Generated on Mon May 24 09:53:30 2010 for TUMBLE by  doxygen 1.5.2