OpenWalnut  1.2.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends
WGEGeometryUtils.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 <map>
00026 #include <string>
00027 #include <vector>
00028 
00029 #include <osg/Array>
00030 #include <osgUtil/DelaunayTriangulator>
00031 
00032 #include "../common/math/linearAlgebra/WLinearAlgebra.h"
00033 #include "WGEGeometryUtils.h"
00034 #include "WGEUtils.h"
00035 #include "WTriangleMesh.h"
00036 #include "exceptions/WGEException.h"
00037 
00038 osg::ref_ptr< osg::Vec3Array > wge::generateCuboidQuads( const std::vector< WPosition >& corners )
00039 {
00040     osg::ref_ptr< osg::Vec3Array > vertices = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
00041 
00042     // Surfaces
00043     vertices->push_back( corners[0] );
00044     vertices->push_back( corners[1] );
00045     vertices->push_back( corners[2] );
00046     vertices->push_back( corners[3] );
00047 
00048     vertices->push_back( corners[1] );
00049     vertices->push_back( corners[5] );
00050     vertices->push_back( corners[6] );
00051     vertices->push_back( corners[2] );
00052 
00053     vertices->push_back( corners[5] );
00054     vertices->push_back( corners[4] );
00055     vertices->push_back( corners[7] );
00056     vertices->push_back( corners[6] );
00057 
00058     vertices->push_back( corners[4] );
00059     vertices->push_back( corners[0] );
00060     vertices->push_back( corners[3] );
00061     vertices->push_back( corners[7] );
00062 
00063     vertices->push_back( corners[3] );
00064     vertices->push_back( corners[2] );
00065     vertices->push_back( corners[6] );
00066     vertices->push_back( corners[7] );
00067 
00068     vertices->push_back( corners[0] );
00069     vertices->push_back( corners[1] );
00070     vertices->push_back( corners[5] );
00071     vertices->push_back( corners[4] );
00072     return vertices;
00073 }
00074 
00075 osg::Vec3 wge::getQuadNormal( const WPosition& a,
00076                               const WPosition& b,
00077                               const WPosition& c )
00078 {
00079     WVector3d vec1 = a - b;
00080     WVector3d vec2 = c - b;
00081     WVector3d normal = cross( vec2, vec1 );
00082     return normalize( normal );
00083 }
00084 
00085 osg::ref_ptr< osg::Vec3Array > wge::generateCuboidQuadNormals( const std::vector< WPosition >& corners )
00086 {
00087     osg::ref_ptr< osg::Vec3Array > vertices = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
00088 
00089     vertices->push_back( getQuadNormal( corners[0], corners[1], corners[2] ) );
00090     vertices->push_back( getQuadNormal( corners[1], corners[5], corners[6] ) );
00091     vertices->push_back( getQuadNormal( corners[5], corners[4], corners[7] ) );
00092     vertices->push_back( getQuadNormal( corners[4], corners[0], corners[3] ) );
00093     vertices->push_back( getQuadNormal( corners[3], corners[2], corners[6] ) );
00094     vertices->push_back( getQuadNormal( corners[0], corners[1], corners[5] ) );
00095     return vertices;
00096 }
00097 
00098 WTriangleMesh::SPtr wge::triangulate( const std::vector< WPosition >& points, double transformationFactor )
00099 {
00100     WAssert( points.size() > 2, "The Delaunay triangulation needs at least 3 vertices!" );
00101 
00102     osg::ref_ptr< osg::Vec3Array > osgPoints = wge::osgVec3Array( points );
00103 
00104     if( transformationFactor != 0.0 )
00105     {
00106         // Transform the points as described in the Doxygen description of
00107         // this function.
00108         osg::Vec3 centroid;
00109         for( std::size_t pointID = 0; pointID < osgPoints->size(); ++pointID )
00110         {
00111             centroid += (*osgPoints)[pointID];
00112         }
00113         centroid /= osgPoints->size();
00114 
00115         for( std::size_t pointID = 0; pointID < osgPoints->size(); ++pointID )
00116         {
00117             const double factor = ( (*osgPoints)[pointID].z() - centroid.z() ) * transformationFactor + 1.0;
00118             (*osgPoints)[pointID].x() = ( (*osgPoints)[pointID].x() - centroid.x() ) * factor + centroid.x();
00119             (*osgPoints)[pointID].y() = ( (*osgPoints)[pointID].y() - centroid.y() ) * factor + centroid.y();
00120         }
00121     }
00122 
00123     // The osg triangulator sorts the points and returns the triangles with
00124     // the indizes of the sorted points. Since we don't want to change the
00125     // sequence of the points, we have to save the original index of each
00126     // point.
00127     std::map< osg::Vec3, size_t > map;
00128     for( size_t index = 0; index < osgPoints->size(); ++index )
00129     {
00130         map[ (*osgPoints)[index] ] = index;
00131     }
00132 
00133     osg::ref_ptr< osgUtil::DelaunayTriangulator > triangulator( new osgUtil::DelaunayTriangulator( osgPoints ) );
00134 
00135     bool triangulationResult = triangulator->triangulate();
00136 
00137     WAssert( triangulationResult, "Something went wrong in triangulation." );
00138 
00139     osg::ref_ptr< const osg::DrawElementsUInt > osgTriangles( triangulator->getTriangles() );
00140     size_t nbTriangles = osgTriangles->size() / 3;
00141     std::vector<  size_t > triangles( osgTriangles->size()  );
00142     for( size_t triangleID = 0; triangleID < nbTriangles; ++triangleID )
00143     {
00144         // Convert the new index of the osgTriangle to the original
00145         // index stored in map.
00146         size_t vertID = triangleID * 3;
00147         triangles[vertID + 0] = map[ (*osgPoints)[ (*osgTriangles)[vertID + 0] ] ];
00148         triangles[vertID + 1] = map[ (*osgPoints)[ (*osgTriangles)[vertID + 1] ] ];
00149         triangles[vertID + 2] = map[ (*osgPoints)[ (*osgTriangles)[vertID + 2] ] ];
00150     }
00151 
00152     // I needed this reconversion using osgVec3Array because the triangulator changed my positions somehow.
00153     return WTriangleMesh::SPtr( new WTriangleMesh( wge::osgVec3Array( points ), triangles ) );
00154 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends