OpenWalnut  1.4.0
WGeometryFunctions.cpp
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #include <vector>
00026 #include <map>
00027 
00028 #include "WGeometryFunctions.h"
00029 
00030 void tesselateIcosahedron( std::vector< WVector3d >* vertices, std::vector< unsigned int >* triangles, unsigned int level )
00031 {
00032     WAssert( vertices, "Missing input vector." );
00033     WAssert( triangles, "Missing input vector." );
00034     vertices->clear();
00035     triangles->clear();
00036 
00037     unsigned int nv = 12;
00038     unsigned int nt = 20;
00039     for( unsigned int t = 1; t <= level; ++t )
00040     {
00041         nv += 3 * nt / 2;
00042         nt *= 4;
00043     }
00044     vertices->reserve( nv );
00045     triangles->reserve( nt );
00046 
00047     // add icosahedron vertices
00048     double phi = 0.5 * ( 1.0 + sqrt( 5.0 ) );
00049 
00050     std::vector< WVector3d > g;
00051 
00052     vertices->push_back( WVector3d( phi, 1, 0 ) ); // 0
00053     vertices->push_back( WVector3d( -phi, 1, 0 ) ); // 1
00054     vertices->push_back( WVector3d( phi, -1, 0 ) ); // 2
00055     vertices->push_back( WVector3d( -phi, -1, 0 ) ); // 3
00056 
00057     vertices->push_back( WVector3d( 1, 0, phi ) ); // 4
00058     vertices->push_back( WVector3d( -1, 0, phi ) ); // 5
00059     vertices->push_back( WVector3d( 1, 0, -phi ) ); // 6
00060     vertices->push_back( WVector3d( -1, 0, -phi ) ); // 7
00061 
00062     vertices->push_back( WVector3d( 0, phi, 1 ) ); // 8
00063     vertices->push_back( WVector3d( 0, -phi, 1 ) ); // 9
00064     vertices->push_back( WVector3d( 0, phi, -1 ) ); // 10
00065     vertices->push_back( WVector3d( 0, -phi, -1 ) ); // 11
00066 
00067     for( std::vector< WVector3d >::iterator it = vertices->begin(); it != vertices->end(); ++it )
00068     {
00069         *it = normalize( *it );
00070     }
00071 
00072     // add triangle indices
00073     unsigned int inc[ 60 ] =
00074     {
00075         8, 5, 4,
00076         8, 4, 0,
00077         8, 0, 10,
00078         8, 10, 1,
00079         8, 1, 5,
00080         5, 9, 4,
00081         4, 2, 0,
00082         0, 6, 10,
00083         10, 7, 1,
00084         1, 3, 5,
00085         4, 9, 2,
00086         0, 2, 6,
00087         10, 6, 7,
00088         1, 7, 3,
00089         5, 3, 9,
00090         9, 11, 2,
00091         2, 11, 6,
00092         6, 11, 7,
00093         7, 11, 3,
00094         3, 11, 9
00095     };
00096     triangles->assign( inc, inc + 60 );
00097 
00098     std::map< utility::Edge, unsigned int > edgeVertices;
00099 
00100     for( unsigned int t = 0; t < level; ++t )
00101     {
00102         // for every triangle
00103         std::size_t numTriangles = triangles->size() / 3;
00104         for( std::size_t k = 0; k < numTriangles; ++k )
00105         {
00106             unsigned int idx[ 3 ];
00107             // generate a new vertex for every edge (if there is no vertex yet)
00108 
00109             for( int i = 0; i < 3; ++i )
00110             {
00111                 utility::Edge e( ( *triangles )[ 3 * k + i ], ( *triangles )[ 3 * k + ( i + 1 ) % 3 ] );
00112                 if( edgeVertices.find( e ) == edgeVertices.end() )
00113                 {
00114                     WVector3d v0 = vertices->at( e.first );
00115                     WVector3d v1 = vertices->at( e.second );
00116                     WVector3d v = v0 + v1;
00117                     v = normalize( v );
00118                     vertices->push_back( v );
00119                     edgeVertices[ e ] = vertices->size() - 1;
00120                 }
00121                 idx[ i ] = edgeVertices[ e ];
00122             }
00123 
00124             // make 4 triangles from the current one
00125             // add 1st triangle
00126             triangles->push_back( ( *triangles )[ 3 * k + 0 ] );
00127             triangles->push_back( idx[ 0 ] );
00128             triangles->push_back( idx[ 2 ] );
00129 
00130             // add 2nd triangle
00131             triangles->push_back( ( *triangles )[ 3 * k + 1 ] );
00132             triangles->push_back( idx[ 1 ] );
00133             triangles->push_back( idx[ 0 ] );
00134 
00135             // add 3rd triangle
00136             triangles->push_back( ( *triangles )[ 3 * k + 2 ] );
00137             triangles->push_back( idx[ 2 ] );
00138             triangles->push_back( idx[ 1 ] );
00139 
00140             // changed indices of this triangle to the indices of the 4th triangle
00141             ( *triangles )[ 3 * k + 0 ] = idx[ 0 ];
00142             ( *triangles )[ 3 * k + 1 ] = idx[ 1 ];
00143             ( *triangles )[ 3 * k + 2 ] = idx[ 2 ];
00144         }
00145         edgeVertices.clear();
00146     }
00147 }