contrib/oul/ouml/polygon_mesh.cxx
Go to the documentation of this file.
00001 // This is oul/ouml/polygon_mesh.cxx
00002 #include "polygon_mesh.h"
00003 //:
00004 // \file
00005 // \brief polygon_mesh.cc: a class for polygon meshes
00006 // \author
00007 // Copyright (c) 2001 Brendan McCane University of Otago, Dunedin, New
00008 // Zealand Reproduction rights limited as described in the COPYRIGHT
00009 // file.
00010 //----------------------------------------------------------------------
00011 
00012 #include <vcl_cstdio.h> // for fscanf()
00013 #include <vcl_iostream.h>
00014 #include <vcl_cassert.h>
00015 #include <vnl/vnl_cross.h>
00016 
00017 //----------------------------------------------------------------------
00018 //: add_vertex
00019 //
00020 // Add a vertex to the end of the list of vertices
00021 //
00022 // \param pt  The location of the vertex
00023 // \return    The position of the added vertex
00024 //
00025 // \author Brendan McCane
00026 //----------------------------------------------------------------------
00027 int PolygonMesh::add_vertex(DPoint &pt)
00028 {
00029   vertex_list.push_back(pt);
00030   return vertex_list.size()-1;
00031 }
00032 
00033 
00034 //----------------------------------------------------------------------
00035 //: add_vertex
00036 //
00037 // Add a vertex to the prescribed position in the list of vertices
00038 //
00039 // \param pt    The location of the vertex
00040 // \param index Where to add the vertex
00041 // \return      The position of the added vertex
00042 //
00043 // \author Brendan McCane
00044 //----------------------------------------------------------------------
00045 
00046 int PolygonMesh::set_vertex(int index, DPoint &pt)
00047 {
00048   assert(index>=0);
00049   if (vertex_list.capacity()<=(unsigned int)index)
00050     vertex_list.reserve(index+100);
00051   vertex_list[index] = pt;
00052   return index;
00053 }
00054 
00055 //----------------------------------------------------------------------
00056 //: add_face
00057 //
00058 // Add a face to the end of the list of faces
00059 //
00060 // \param fc The vertices associated with the face
00061 // \return   The position of the added face
00062 //
00063 // \author Brendan McCane
00064 //----------------------------------------------------------------------
00065 
00066 int PolygonMesh::add_face(Face &fc)
00067 {
00068   face_list.push_back(fc);
00069   return face_list.size()-1;
00070 }
00071 
00072 //----------------------------------------------------------------------
00073 //: add_face
00074 //
00075 // Add a face to the prescribed position in the list of faces
00076 //
00077 // \param fc    The vertices associated with the face
00078 // \param index Where to add the face
00079 // \return      The position of the added face
00080 //
00081 // \author Brendan McCane
00082 //----------------------------------------------------------------------
00083 
00084 int PolygonMesh::set_face(int index, Face &fc)
00085 {
00086   assert(index>=0);
00087   if (face_list.capacity()<=(unsigned int)index)
00088     face_list.reserve(index+100);
00089   face_list[index] = fc;
00090   return index;
00091 }
00092 
00093 //----------------------------------------------------------------------
00094 //: get_vertex
00095 //
00096 // Returns a vertex at the specified location
00097 //
00098 // \param index the position to return
00099 // \return      the position of the vertex
00100 //
00101 // \author Brendan McCane
00102 //----------------------------------------------------------------------
00103 
00104 PolygonMesh::DPoint PolygonMesh::get_vertex(int index)
00105 {
00106   assert(index >= 0);
00107   if ((unsigned int)index>=vertex_list.size())
00108   {
00109     vcl_cerr << "Warning: vertex doesn't exist\n";
00110     return DPoint();
00111   }
00112   return vertex_list[index];
00113 }
00114 
00115 //----------------------------------------------------------------------
00116 //: get_face
00117 //
00118 // Returns a face at the specified location
00119 //
00120 // \param index  the position to return
00121 // \return       a list of vertices
00122 //
00123 // \author Brendan McCane
00124 //----------------------------------------------------------------------
00125 
00126 PolygonMesh::Polygon PolygonMesh::get_face(int index)
00127 {
00128   assert(index >= 0);
00129   Polygon poly;
00130   if ((unsigned int)index>=face_list.size())
00131   {
00132     vcl_cerr << "Warning: face doesn't exist\n";
00133     return poly;
00134   }
00135   Face& face = face_list[index];
00136   for (unsigned int i=0; i<face.size(); i++)
00137     poly.push_back(vertex_list[face[i]]);
00138   return poly;
00139 }
00140 
00141 
00142 //----------------------------------------------------------------------
00143 //: read_file
00144 //
00145 // read a mesh in from a file
00146 //
00147 // \param filename  the name of the file
00148 // \return          whether or not the file was successfully read
00149 //
00150 // \author Brendan McCane
00151 //----------------------------------------------------------------------
00152 
00153 bool PolygonMesh::read_file(char *filename)
00154 {
00155   char start[100];
00156   FILE *fp=vcl_fopen(filename, "r");
00157   if (!fp) return false;
00158 
00159   while (vcl_fscanf(fp, "%s", start)!=EOF)
00160   {
00161     if (!vcl_strcmp(start, "Vertex")) // read in a vertex
00162     {
00163       int index;
00164       double x, y, z;
00165       int ret = vcl_fscanf(fp, "%d %lf %lf %lf", &index, &x, &y, &z); if (ret<4) return false;
00166       // add the vertex
00167       DPoint pt(x,y,z);
00168       //vcl_printf("Vertex: %d %f %f %f\n", index, x, y, z);
00169       set_vertex(index, pt);
00170     }
00171     else if (!vcl_strcmp(start, "Face")) // read in a face
00172     {
00173       int index;
00174       int vertex;
00175       Face fc;
00176       int ret = vcl_fscanf(fp, "%d", &index); if (ret<1) return false;
00177       //vcl_printf("Face: %d ", index);
00178       // read in all the vertex indices
00179       while ((vcl_fscanf(fp, "%d", &vertex)))
00180       {
00181         //vcl_printf("%d ", vertex);
00182         fc.push_back(vertex);
00183       }
00184       //vcl_printf("\n");
00185       set_face(index, fc);
00186     }
00187     else if (!vcl_strcmp(start, "End")) // end of mesh
00188       break;
00189     else // assume comment, read to eoln
00190     {
00191       char c;
00192       do {
00193         int ret = vcl_fscanf(fp, "%c", &c); if (ret<1) return false;
00194       } while (c!='\n');
00195     }
00196   }
00197 
00198   return true;
00199 }
00200 
00201 //----------------------------------------------------------------------
00202 //: get_face_normal
00203 //
00204 // return the normal vector for the given vertex of a given face.
00205 //
00206 // \param face_index    which face
00207 //
00208 // \param vertex_index  which vertex in the face (ie not the
00209 // vertex index in the entire list of vertices, but the vertex index
00210 // within the face).
00211 //
00212 // \return the normalised normal vector
00213 //
00214 // \author Brendan McCane
00215 //----------------------------------------------------------------------
00216 
00217 PolygonMesh::DVector3D PolygonMesh::get_face_normal
00218 (
00219   int face_index,
00220   int /*vertex_index*/
00221 )
00222 {
00223   assert(face_index>=0);
00224   assert((unsigned int)face_index<face_list.size());
00225   // in this version, I'm just returning the same vector for all vertices - TODO
00226   // Therefore I need to find the cross-product of two vectors lying
00227   // on the plane of the polygon.
00228   Polygon face = get_face(face_index);
00229   DVector3D v1(face[0].x()-face[1].x(), face[0].y()-face[1].y(),
00230                face[0].z()-face[1].z());
00231   DVector3D v2(face[0].x()-face[2].x(), face[0].y()-face[2].y(),
00232                face[0].z()-face[2].z());
00233   DVector3D cross = vnl_cross_3d(v1, v2);
00234   cross.normalize();
00235   return cross;
00236 }