zsig 1.0.0

include/signaturet.hh

Go to the documentation of this file.
00001 
00008 #ifndef ZSIG_SIGNATURET_HH
00009 #define ZSIG_SIGNATURET_HH
00010 
00011 //== INCLUDES =================================================================
00012 
00013 #include <set>
00014 #include <vector>
00015 #include <limits>
00016 #include <fstream>
00017 #include <iostream>
00018 
00019 #include <vec.hh>
00020 
00021 //== NAMESPACES ===============================================================
00022 
00023 namespace zsig {
00024 
00025 //== CLASS DEFINITION =========================================================
00026 
00038 template< unsigned R, unsigned C, class T >
00039 class SignatureT {
00040 
00041 public:
00042 
00043         typedef SignatureT< R, C, T > signature_type; 
00044 
00046         SignatureT() {
00047                 sig = new T*[R];
00048                 for (unsigned i = 0; i < R; ++i)
00049                         sig[i] = new T[C];
00050                 this->clear();
00051         }
00052 
00056         SignatureT( const SignatureT& _sig ) {
00057                 sig = new T*[R];
00058                 for (unsigned i = 0; i < R; ++i)
00059                         sig[i] = new T[C];
00060                 *this = _sig;
00061         }
00062 
00064         ~SignatureT() {
00065                 for (unsigned i = 0; i < R; ++i)
00066                         delete [] sig[i];
00067                 delete [] sig;
00068         }
00069 
00071         void clear( void ) {
00072                 for (unsigned i = 0; i < R; ++i)
00073                         for (unsigned j = 0; j < C; ++j)
00074                                 sig[i][j] = T();
00075         }
00076 
00081         signature_type& operator = ( const signature_type& _sig ) {
00082                 for (unsigned i = 0; i < R; ++i)
00083                         for (unsigned j = 0; j < C; ++j)
00084                                 sig[i][j] = _sig[i][j];
00085                 return *this;
00086         }
00087 
00093         T* operator [] ( const unsigned& _i ) { return this->sig[_i]; }
00094 
00100         const T* operator [] ( const unsigned& _i ) const { return this->sig[_i]; }
00101 
00108         friend std::ostream& operator << ( std::ostream& out,
00109                                            const signature_type& _s ) {
00110                 for (unsigned i = 0; i < R; ++i) {
00111                         out << _s[i][0];
00112                         for (unsigned j = 1; j < C; ++j)
00113                                 out << " " << _s[i][j];
00114                         if( i < R-1 ) out << "\n";
00115                 }
00116                 return out;
00117         }
00118 
00125         friend std::istream& operator >> ( std::istream& in,
00126                                            signature_type& _s ) {
00127                 for (unsigned i = 0; i < R; ++i)
00128                         for (unsigned j = 0; j < C; ++j)
00129                                 in >> _s[i][j];
00130                 return in;
00131         }
00132 
00137         T** operator &( void ) { return (T**)this->sig; }
00138 
00143         const T** operator &( void ) const { return (const T**)this->sig; }
00144 
00145 private:
00146 
00147         T **sig; 
00148 
00149 };
00158 //== CLASS DEFINITION =========================================================
00159 
00170 template< class T >
00171 class SignatureMeshT {
00172 
00173 public:
00174 
00175         typedef vec< 3, T > vec3; 
00176         typedef vec< 3, unsigned > uvec3; 
00177         typedef SignatureMeshT< T > mesh_type; 
00178         typedef std::vector< unsigned > index_list; 
00179         typedef vec3 bbox_type [2]; 
00180         typedef vec3 sigplane_type [4]; 
00181 
00183         SignatureMeshT() : nv(0), nf(0), gd(0), va(0), fa(0), gfa(0), fna(0) { }
00184 
00188         SignatureMeshT( const mesh_type& _m ) : nv(0), nf(0), gd(0), va(0), fa(0), gfa(0), fna(0) { *this = _m; }
00189 
00191         ~SignatureMeshT() { this->clear(); }
00192 
00194         void clear( void ) {
00195                 nv = nf = gd = 0; msd = (T)0;
00196                 if( va ) { delete [] va; va = 0; }
00197                 if( fa ) { delete [] fa; fa = 0; }
00198                 if( gfa ) { delete [] gfa; gfa = 0; }
00199                 if( fna ) { delete [] fna; fna = 0; }
00200                 nfv.clear();
00201                 bb[0].clear();
00202                 bb[1].clear();
00203                 diag.clear();
00204         }
00205 
00210         mesh_type& operator = ( const mesh_type& _m ) {
00211                 this->clear();
00212                 this->set_vertices( _m.size_of_vertices(), _m.vertices() );
00213                 this->set_faces( _m.size_of_faces(), _m.faces() );
00214                 this->set_grid( _m.grid_dimension(), _m.grid(), _m.maximum_search_distance() );
00215                 this->set_fnormals( _m.size_of_faces(), _m.fnormals() );
00216                 this->set_neighborhood( _m.neighborhood() );
00217                 this->set_bbox( _m.bounding_box(), _m.diagonal() );
00218                 return *this;
00219         }
00220 
00221         // @name I/O functions
00223 
00227         void read_off( std::istream& _in ) {
00228                 std::string h; // (unused) header line
00229                 unsigned ne; // (unused) number of edges
00230                 this->clear();
00231                 _in >> h >> nv >> nf >> ne;
00232                 va = new vec3[ nv ];
00233                 fa = new uvec3[ nf ];
00234                 unsigned nvf; // (unused) number of vertices per face
00235                 for (unsigned i = 0; i < nv; ++i)
00236                         _in >> va[i];
00237                 for (unsigned i = 0; i < nf; ++i)
00238                         _in >> nvf >> fa[i];
00239         }
00240 
00244         void read_off( const char* fn ) {
00245                 std::fstream in( fn, std::ios::in );
00246                 read_off( in );
00247                 in.close();
00248         }
00249 
00253         void write_off( std::ostream& _out ) const {
00254                 _out << "OFF\n" << nv << " " << nf << " 0\n";
00255                 for (unsigned i = 0; i < nv; ++i)
00256                         _out << va[i] << "\n";
00257                 for (unsigned i = 0; i < nf; ++i)
00258                         _out << "3 " << fa[i] << "\n";
00259         }
00260 
00264         void write_off( const char* fn ) const {
00265                 std::fstream out( fn, std::ios::out );
00266                 write_off( out );
00267                 out.close();
00268         }
00269 
00274         void write_ply( std::ostream& _out, const uvec3 *_colors ) const {
00275                 _out << "ply\nformat ascii 1.0\n";
00276                 _out << "element vertex " << nv << " \n";
00277                 _out << "property float x\nproperty float y\nproperty float z\n";
00278                 _out << "property uchar red\nproperty uchar green\nproperty uchar blue\n";
00279                 _out << "element face " << nf << " \n";
00280                 _out << "property list uchar int vertex_indices\n";
00281                 _out << "end_header\n";
00282                 for (unsigned i = 0; i < nv; ++i)
00283                         _out << va[i] << " " << _colors[i] << "\n";
00284                 for (unsigned i = 0; i < nf; ++i)
00285                         _out << "3 " << fa[i] << "\n";
00286         }
00287 
00292         void write_ply( const char* fn, const uvec3 *_colors ) const {
00293                 std::fstream out( fn, std::ios::out );
00294                 write_ply( out, _colors );
00295                 out.close();
00296         }
00297 
00299 
00300         // @name Build functions
00302 
00310         void build_all( void ) {
00311                 build_bbox();
00312                 build_neighborhood();
00313                 build_fnormals();
00314                 build_grid();
00315         }
00316 
00320         void build_grid( T& _msd ) {
00321                 if( gfa ) delete [] gfa;
00322                 T msl = diag[0]; // maximum side length
00323                 msl = std::max( msl, diag[1] );
00324                 msl = std::max( msl, diag[2] );
00325                 gd = ceil( msl / _msd );
00326                 gfa = new std::vector< unsigned >[ gd * gd * gd ];
00327                 uvec3 gp; // grid position
00328                 for (unsigned i = 0; i < nf; ++i) {
00329                         for (unsigned j = 0; j < 3; ++j) {
00330                                 convert_to_grid( va[ fa[i][j] ], gp );
00331                                 gfa[ gp[0]*gd*gd + gp[1]*gd + gp[2] ].push_back( i );
00332                         } // j
00333                 } // i
00334                 msd = _msd;
00335         }
00336 
00344         void build_grid( void ) {
00345                 msd = diagonal_distance() / (T)40; // _msd = 2.5 % of diagonal bounding box
00346                 if( msd ) build_grid( msd );
00347         }
00348 
00350         void build_fnormals( void ) {
00351                 if( fna ) delete [] fna;
00352                 fna = new vec3[ nf ];
00353                 vec3 fv[3]; // face vertices
00354                 for (unsigned i = 0; i < nf; ++i) {
00355                         for (unsigned k = 0; k < 3; ++k)
00356                                 fv[k] = va[ fa[i][k] ];
00357                         // considering counter-clockwise orientation
00358                         // in faces when computing face normal
00359                         fna[i] = ( fv[1] - fv[0] ) % ( fv[2] - fv[0] );
00360                 }
00361         }
00362 
00364         void build_neighborhood( void ) {
00365                 nfv.clear();
00366                 nfv.resize( nv );
00367                 for (unsigned i = 0; i < nf; ++i) {
00368                         nfv[ fa[i][0] ].push_back( i );
00369                         nfv[ fa[i][1] ].push_back( i );
00370                         nfv[ fa[i][2] ].push_back( i );
00371                 }
00372         }
00373 
00375         void build_bbox( void ) {
00376                 if( !va ) { bb[0].clear(); bb[1].clear(); diag.clear(); return; }
00377                 bb[1] = bb[0] = va[0];
00378                 for (unsigned i = 1; i < nv; ++i) {
00379                         for (unsigned k = 0; k < 3; ++k) {
00380                                 if( va[i][k] < bb[0][k] ) bb[0][k] = va[i][k];
00381                                 if( va[i][k] > bb[1][k] ) bb[1][k] = va[i][k];
00382                         }
00383                 }
00384                 diag = bb[1] - bb[0];
00385         }
00386 
00388 
00389         // @name Compute functions
00391 
00402         void compute_neighborhood( const unsigned& _i,
00403                                    std::set< unsigned >& _nb,
00404                                    const bool& _v = false ) const {
00405                 vec3 v = va[ _i ]; // vertex position
00406                 uvec3 gp; // grid position of vertex
00407                 convert_to_grid( v, gp );
00408                 _nb.clear();
00409                 for (unsigned ci = std::max((int)gp[0]-1, 0); ci <= std::min((int)gp[0]+1, (int)gd-1); ++ci) {
00410                         for (unsigned cj = std::max((int)gp[1]-1, 0); cj <= std::min((int)gp[1]+1, (int)gd-1); ++cj) {
00411                                 for (unsigned ck = std::max((int)gp[2]-1, 0); ck <= std::min((int)gp[2]+1, (int)gd-1); ++ck) {
00412                                         for (unsigned i = 0; i < gfa[ci*gd*gd+cj*gd+ck].size(); ++i) {
00413                                                 unsigned fi = gfa[ci*gd*gd+cj*gd+ck][i];
00414                                                 for (unsigned vi = 0; vi < 3; ++vi) {
00415                                                         vec3 ov = va[ fa[fi][vi] ];
00416                                                         if( (ov - v).length() <= msd ) {
00417                                                                 if( _v ) {
00418                                                                         _nb.insert( fa[fi][vi] );
00419                                                                 } else {
00420                                                                         _nb.insert( fi );
00421                                                                         break;
00422                                                                 } // else
00423                                                         } // if
00424                                                 } // vi
00425                                         } // i
00426                                 } // ck
00427                         } // cj
00428                 } // ci
00429         }
00430 
00439         void compute_sigplane( const unsigned& _i, sigplane_type& _sp ) const {
00440                 _sp[0] = va[ _i ];
00441                 compute_normal( _i, _sp[3] );
00442                 _sp[3].normalize();
00443                 // get any vertex connected to the given vertex,
00444                 // project it onto the tangent plane, and use it to
00445                 // stipulate the vector Y of the LCF; it does not
00446                 // matter which vector Y is since the signature will
00447                 // be converted to Zernike coefficients becoming
00448                 // rotationally invariant
00449                 unsigned k = 0;
00450                 while( k < 2 and fa[ nfv[ _i ][0] ][k] == _i ) ++k;
00451                 _sp[2] = va[ fa[ nfv[ _i ][0] ][k] ]; // other vertex
00452                 project_vertex( _sp[2], _sp[3], _sp[0] );
00453                 _sp[2] -= _sp[0];
00454                 _sp[2].normalize();
00455                 _sp[1] = _sp[2] % _sp[3];
00456         }
00457 
00466         void compute_normal( const unsigned& _i, vec3& _n ) const {
00467                 _n.clear();
00468                 for (unsigned fi = 0; fi < nfv[_i].size(); ++fi)
00469                         _n += fna[ nfv[_i][fi] ];
00470                 _n /= nfv[_i].size();
00471         }
00472 
00474 
00475         // @name Set functions
00477 
00482         void set_vertices( const unsigned& _nv, const vec3 *_va ) {
00483                 if( !_va ) return;
00484                 nv = _nv;
00485                 if( va ) delete [] va;
00486                 va = new vec3[ nv ];
00487                 for (unsigned i = 0; i < nv; ++i)
00488                         va[i] = _va[i];
00489         }
00490 
00495         void set_faces( const unsigned& _nf, const uvec3 *_fa ) {
00496                 if( !_fa ) return;
00497                 nf = _nf;
00498                 if( fa ) delete [] fa;
00499                 fa = new uvec3[ nf ];
00500                 for (unsigned i = 0; i < nf; ++i)
00501                         fa[i] = _fa[i];
00502         }
00503 
00509         void set_grid( const unsigned& _gd, const index_list *_gfa, const T& _msd ) {
00510                 if( !_gfa ) return;
00511                 gd = _gd;
00512                 if( gfa ) delete [] gfa;
00513                 gfa = new index_list[ gd * gd * gd ];
00514                 for (unsigned i = 0; i < gd; ++i)
00515                         for (unsigned j = 0; j < gd; ++j)
00516                                 for (unsigned k = 0; k < gd; ++k)
00517                                         gfa[ i*gd*gd + j*gd + k ] = _gfa[ i*gd*gd + j*gd + k ];
00518                 msd = _msd;
00519         }
00520 
00525         void set_fnormals( const unsigned& _nf, const vec3 *_fna ) {
00526                 if( !_fna ) return;
00527                 if( fna ) delete [] fna;
00528                 fna = new vec3[ _nf ];
00529                 for (unsigned i = 0; i < _nf; ++i)
00530                         fna[i] = _fna[i];
00531         }
00532 
00536         void set_neighborhood( const std::vector< index_list >& _nfv ) {
00537                 nfv = _nfv;
00538         }
00539 
00544         void set_bbox( const bbox_type& _bb, const vec3& _diag ) {
00545                 bb[0] = _bb[0];
00546                 bb[1] = _bb[1];
00547                 diag = _diag;
00548         }
00549 
00551 
00552         // @name Get functions
00554 
00558         unsigned size_of_vertices( void ) const { return nv; }
00559 
00563         unsigned size_of_faces( void ) const { return nf; }
00564 
00568         unsigned grid_dimension( void ) const { return gd; }
00569 
00573         vec3 *vertices( void ) { return va; }
00574 
00578         const vec3 *vertices( void ) const { return va; }
00579 
00583         uvec3 *faces( void ) { return fa; }
00584 
00588         const uvec3 *faces( void ) const { return fa; }
00589 
00593         index_list *grid( void ) { return gfa; }
00594 
00598         const index_list *grid( void ) const { return gfa; }
00599 
00603         T& maximum_search_distance( void ) { return msd; }
00604 
00608         const T& maximum_search_distance( void ) const { return msd; }
00609 
00613         vec3 *fnormals( void ) { return fna; }
00614 
00618         const vec3 *fnormals( void ) const { return fna; }
00619 
00623         std::vector< index_list >& neighborhood( void ) { return nfv; }
00624 
00628         const std::vector< index_list >& neighborhood( void ) const { return nfv; }
00629 
00633         bbox_type& bounding_box( void ) { return bb; }
00634 
00638         const bbox_type& bounding_box( void ) const { return bb; }
00639 
00643         vec3& diagonal( void ) { return diag; }
00644 
00648         const vec3& diagonal( void ) const { return diag; }
00649 
00653         T diagonal_distance( void ) const { return diag.length(); }
00654 
00656 
00657 protected:
00658 
00663         void convert_to_grid( const vec3& _p, uvec3& _g ) const {
00664                 vec3 bp = (_p - bb[0]) / diag; // bounding box relative position
00665                 _g[0] = std::min( (unsigned)(bp[0] * gd), gd-1 );
00666                 _g[1] = std::min( (unsigned)(bp[1] * gd), gd-1 );
00667                 _g[2] = std::min( (unsigned)(bp[2] * gd), gd-1 );
00668         }
00669 
00670 private:
00671 
00672         unsigned nv, nf, gd; 
00673         vec3 *va; 
00674         uvec3 *fa; 
00675         index_list *gfa; 
00676         T msd; 
00677         vec3 *fna; 
00678         std::vector< index_list > nfv; 
00679         bbox_type bb; 
00680         vec3 diag; 
00681 
00682 };
00691 //=== IMPLEMENTATION ==========================================================
00692 
00709 template< unsigned R, unsigned C, class T >
00710 void compute_signature( SignatureT< R, C, T >& _sig,
00711                         const SignatureMeshT< T >& _m,
00712                         const unsigned& _i ) {
00713 
00714         typedef typename SignatureMeshT< T >::vec3 vec3;
00715         typedef typename SignatureMeshT< T >::sigplane_type sigplane_type;
00716 
00717         sigplane_type sp; // tangent plane on top of the vertex
00718 
00719         _m.compute_sigplane( _i, sp );
00720 
00721         T hmr = _m.maximum_search_distance(); // heightmap radius
00722         T inf = 1.5 * hmr; // heightmap infinity value
00723         vec3 vX, vY, vZ; // three generic vectors used throughout this function
00724 
00725         vX = sp[1] * hmr; // vector base of tangent plane in X
00726         vY = sp[2] * hmr; // vector base of tangent plane in Y
00727 
00728         vec3 pq[4]; // tangent plane quad border points
00729 
00730         pq[0] = sp[0] - vX - vY;
00731         pq[1] = sp[0] + vX - vY;
00732         pq[2] = sp[0] + vX + vY;
00733         pq[3] = sp[0] - vX + vY;
00734 
00735         vX = pq[1] - pq[0];
00736         vY = pq[3] - pq[0];
00737 
00738         T lx = vX.sqrl(); // squared length of vector X
00739         T ly = vY.sqrl(); // squared length of vector Y
00740 
00741         vec3 di, dj; // tangent plane cell supporting vectors
00742 
00743         di = vY / (T)R;
00744         dj = vX / (T)C;
00745 
00746         std::set< unsigned > nf; // neighborhood of faces to be consider around vertex
00747         _m.compute_neighborhood( _i, nf );
00748 
00749         // auxiliary data structure storing faces to be considered for each cell
00750         std::vector< unsigned > grid_faces[ R ][ C ];
00751         unsigned fi; // current face index
00752         int bb[2][2]; // face bounding box over the plane
00753         vec3 bp, lp; // base and line points
00754         T u, v; // (u, v) position over the plane
00755         int gi, gj; // (i, j) grid discrete position
00756 
00757         // build auxiliary grid cell faces data structure
00758         for (std::set< unsigned >::iterator sit = nf.begin(); sit != nf.end(); ++sit) {
00759 
00760                 fi = *sit;
00761                 bb[0][0] = R; bb[0][1] = C; bb[1][0] = bb[1][1] = -1; // reset bounding box
00762 
00763                 // compute the current face's bounding box over the plane
00764                 for (unsigned vi = 0; vi < 3; ++vi) {
00765 
00766                         bp = _m.vertices()[ _m.faces()[fi][vi] ]; // face vertex position = base point
00767 
00768                         project_vertex( bp, sp[3], sp[0] ); // project point onto tangent plane
00769 
00770                         bp -= pq[0]; // converting projected base point to plane vector
00771 
00772                         u = ( bp ^ vX ) / lx; // computing (u, v) position over the plane
00773                         v = ( bp ^ vY ) / ly;
00774 
00775                         gi = (int)( v * R ); // discretizing (u, v)
00776                         gj = (int)( u * C );
00777 
00778                         // [0, 1] -> |--|-..-| last bar (1) is the last grid cell also
00779                         if( gi >= R ) gi = R - 1;
00780                         if( gj >= C ) gj = C - 1;
00781                         if( gi < 0 ) gi = 0;
00782                         if( gj < 0 ) gj = 0;
00783 
00784                         if( gi < bb[0][0] ) bb[0][0] = gi; // update bounding box
00785                         if( gi > bb[1][0] ) bb[1][0] = gi;
00786                         if( gj < bb[0][1] ) bb[0][1] = gj;
00787                         if( gj > bb[1][1] ) bb[1][1] = gj;
00788 
00789                 }
00790 
00791                 // insert face on all grid cells inside the face bounding box
00792                 for (gi = bb[0][0]; gi <= bb[1][0]; ++gi)
00793                         for (gj = bb[0][1]; gj <= bb[1][1]; ++gj)
00794                                 grid_faces[gi][gj].push_back( *sit );
00795 
00796         } // sit
00797 
00798         T x, y; // (x, y) position over the plane
00799         T hitt; // hitted t line parameter
00800         T det; // determinant of intersection matrix
00801         vec< 3, vec3 > inv; // inverse of intersection matrix
00802         vec3 fn; // current face normal
00803         vec3 p0, p1, p2; // current face vertices
00804         vec3 b, ipoint; // target vector and intersection point
00805         T t; // intersection line parameter
00806 
00807         bp = pq[0] + ( di * 0.5 ) + ( dj * 0.5 ); // base point at the center of cell
00808         vZ = sp[3]; // tangent normal
00809 
00810         _sig.clear();
00811 
00812         for (gi = 0; gi < R; ++gi) { // for each grid row
00813 
00814                 y = ( (T)2 * gi + (T)1 ) / (T)R - (T)1;
00815 
00816                 for (gj = 0; gj < C; ++gj) { // for each grid column
00817 
00818                         _sig[gi][gj] = inf; // set the current grid cell to infinity height
00819 
00820                         hitt = std::numeric_limits< T >::max(); // set the current hit t to infinity
00821 
00822                         x = ( (T)2 * gj + (T)1 ) / (T)C - (T)1;
00823                         
00824                         if( sqrt( x*x + y*y ) > (T)1 ) continue; // compute heightmap signature only inside unit disk
00825 
00826                         lp = bp + ( di * gi ) + ( dj * gj ); // define cell's line by the current grid cell center point
00827 
00828                         // shoot rays in both direction (over the cell's line) to find intersections
00829                         for (std::vector< unsigned >::iterator vit = grid_faces[gi][gj].begin(); vit != grid_faces[gi][gj].end(); ++vit) {
00830 
00831                                 fi = *vit;
00832 
00833                                 fn = _m.fnormals()[ fi ]; // current face normal
00834 
00835                                 // define three vertices of the current triangular face
00836                                 p0 = _m.vertices()[ _m.faces()[fi][0] ];
00837                                 p1 = _m.vertices()[ _m.faces()[fi][1] ];
00838                                 p2 = _m.vertices()[ _m.faces()[fi][2] ];
00839 
00840                                 // the intersection matrix A is defined by three vectors:
00841                                 //   vX vector from p0 to p1; vY vector from p0 to p2; vZ the tangent-plane normal
00842                                 vX = p1 - p0; 
00843                                 vY = p2 - p0;
00844 
00845                                 // compute the determinant of the intersection matrix:
00846                                 //   A = |  vZ   vX   vY  |
00847                                 det = vZ[0] * vX[1] * vY[2] - vZ[0] * vY[1] * vX[2]
00848                                 + vX[0] * vY[1] * vZ[2] - vX[0] * vZ[1] * vY[2]
00849                                 + vY[0] * vZ[1] * vX[2] - vY[0] * vX[1] * vZ[2];
00850 
00851                                 // if the intersection matrix is linearly dependent..
00852                                 if( fabs(det) < 1e-5 ) continue; //.. skip this face
00853 
00854                                 // compute the inverse intersection matrix:
00855                                 //   A^-1 = ( 1 / det ) * transpose of cofactor matrix
00856                                 inv[0][0] = ( vX[1] * vY[2] - vY[1] * vX[2] ) / det;
00857                                 inv[0][1] = ( vY[0] * vX[2] - vX[0] * vY[2] ) / det;
00858                                 inv[0][2] = ( vX[0] * vY[1] - vY[0] * vX[1] ) / det;
00859 
00860                                 inv[1][0] = ( vY[1] * vZ[2] - vZ[1] * vY[2] ) / det;
00861                                 inv[1][1] = ( vZ[0] * vY[2] - vY[0] * vZ[2] ) / det;
00862                                 inv[1][2] = ( vY[0] * vZ[1] - vZ[0] * vY[1] ) / det;
00863 
00864                                 inv[2][0] = ( vZ[1] * vX[2] - vX[1] * vZ[2] ) / det;
00865                                 inv[2][1] = ( vX[0] * vZ[2] - vZ[0] * vX[2] ) / det;
00866                                 inv[2][2] = ( vZ[0] * vX[1] - vX[0] * vZ[1] ) / det;
00867 
00868                                 // target vector b of the intersection linear system: A x = b
00869                                 //   x = | t u v |^T
00870                                 //   b = | point in line - point in triangle |
00871                                 b = lp - p0;
00872 
00873                                 // compute intersection point (u, v) parameters by x = A^-1 * b
00874                                 u = inv[1] ^ b;
00875                                 v = inv[2] ^ b;
00876 
00877                                 // test if the intersection point is inside triangle
00878                                 if( u >= 0.0 and u <= 1.0 and v >= 0.0 and v <= 1.0 and (u+v) <= 1.0 ) {
00879 
00880                                         // compute intersection point line parameter t
00881                                         t = inv[0] ^ b;
00882 
00883                                         if( fabs(t) > fabs(hitt) ) continue;
00884 
00885                                         hitt = t;
00886 
00887                                         _sig[gi][gj] = t;
00888 
00889                                 } // if
00890 
00891                         } // vit
00892 
00893                 } // gj
00894 
00895         } // gi
00896 
00897 }
00898 
00899 //=============================================================================
00900 } // namespace zsig
00901 //=============================================================================
00902 #endif // ZSIG_SIGNATURET_HH
00903 //=============================================================================
 All Classes Files Functions Variables Typedefs Friends