OpenWalnut  1.3.1
WGEGeometryUtils.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <map>
26 #include <string>
27 #include <vector>
28 
29 #include <osg/Array>
30 #include <osgUtil/DelaunayTriangulator>
31 
32 #include "../common/math/linearAlgebra/WLinearAlgebra.h"
33 #include "WGEGeometryUtils.h"
34 #include "WGEUtils.h"
35 #include "WTriangleMesh.h"
36 #include "exceptions/WGEException.h"
37 
38 osg::ref_ptr< osg::Vec3Array > wge::generateCuboidQuads( const std::vector< WPosition >& corners )
39 {
40  osg::ref_ptr< osg::Vec3Array > vertices = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
41 
42  // Surfaces
43  vertices->push_back( corners[0] );
44  vertices->push_back( corners[1] );
45  vertices->push_back( corners[2] );
46  vertices->push_back( corners[3] );
47 
48  vertices->push_back( corners[1] );
49  vertices->push_back( corners[5] );
50  vertices->push_back( corners[6] );
51  vertices->push_back( corners[2] );
52 
53  vertices->push_back( corners[5] );
54  vertices->push_back( corners[4] );
55  vertices->push_back( corners[7] );
56  vertices->push_back( corners[6] );
57 
58  vertices->push_back( corners[4] );
59  vertices->push_back( corners[0] );
60  vertices->push_back( corners[3] );
61  vertices->push_back( corners[7] );
62 
63  vertices->push_back( corners[3] );
64  vertices->push_back( corners[2] );
65  vertices->push_back( corners[6] );
66  vertices->push_back( corners[7] );
67 
68  vertices->push_back( corners[0] );
69  vertices->push_back( corners[1] );
70  vertices->push_back( corners[5] );
71  vertices->push_back( corners[4] );
72  return vertices;
73 }
74 
75 osg::Vec3 wge::getQuadNormal( const WPosition& a,
76  const WPosition& b,
77  const WPosition& c )
78 {
79  WVector3d vec1 = a - b;
80  WVector3d vec2 = c - b;
81  WVector3d normal = cross( vec2, vec1 );
82  return normalize( normal );
83 }
84 
85 osg::ref_ptr< osg::Vec3Array > wge::generateCuboidQuadNormals( const std::vector< WPosition >& corners )
86 {
87  osg::ref_ptr< osg::Vec3Array > vertices = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
88 
89  vertices->push_back( getQuadNormal( corners[0], corners[1], corners[2] ) );
90  vertices->push_back( getQuadNormal( corners[1], corners[5], corners[6] ) );
91  vertices->push_back( getQuadNormal( corners[5], corners[4], corners[7] ) );
92  vertices->push_back( getQuadNormal( corners[4], corners[0], corners[3] ) );
93  vertices->push_back( getQuadNormal( corners[3], corners[2], corners[6] ) );
94  vertices->push_back( getQuadNormal( corners[0], corners[1], corners[5] ) );
95  return vertices;
96 }
97 
98 WTriangleMesh::SPtr wge::triangulate( const std::vector< WPosition >& points, double transformationFactor )
99 {
100  WAssert( points.size() > 2, "The Delaunay triangulation needs at least 3 vertices!" );
101 
102  osg::ref_ptr< osg::Vec3Array > osgPoints = wge::osgVec3Array( points );
103 
104  if( transformationFactor != 0.0 )
105  {
106  // Transform the points as described in the Doxygen description of
107  // this function.
108  osg::Vec3 centroid;
109  for( std::size_t pointID = 0; pointID < osgPoints->size(); ++pointID )
110  {
111  centroid += (*osgPoints)[pointID];
112  }
113  centroid /= osgPoints->size();
114 
115  for( std::size_t pointID = 0; pointID < osgPoints->size(); ++pointID )
116  {
117  const double factor = ( (*osgPoints)[pointID].z() - centroid.z() ) * transformationFactor + 1.0;
118  (*osgPoints)[pointID].x() = ( (*osgPoints)[pointID].x() - centroid.x() ) * factor + centroid.x();
119  (*osgPoints)[pointID].y() = ( (*osgPoints)[pointID].y() - centroid.y() ) * factor + centroid.y();
120  }
121  }
122 
123  // The osg triangulator sorts the points and returns the triangles with
124  // the indizes of the sorted points. Since we don't want to change the
125  // sequence of the points, we have to save the original index of each
126  // point.
127  std::map< osg::Vec3, size_t > map;
128  for( size_t index = 0; index < osgPoints->size(); ++index )
129  {
130  map[ (*osgPoints)[index] ] = index;
131  }
132 
133  osg::ref_ptr< osgUtil::DelaunayTriangulator > triangulator( new osgUtil::DelaunayTriangulator( osgPoints ) );
134 
135  bool triangulationResult = triangulator->triangulate();
136 
137  WAssert( triangulationResult, "Something went wrong in triangulation." );
138 
139  osg::ref_ptr< const osg::DrawElementsUInt > osgTriangles( triangulator->getTriangles() );
140  size_t nbTriangles = osgTriangles->size() / 3;
141  std::vector< size_t > triangles( osgTriangles->size() );
142  for( size_t triangleID = 0; triangleID < nbTriangles; ++triangleID )
143  {
144  // Convert the new index of the osgTriangle to the original
145  // index stored in map.
146  size_t vertID = triangleID * 3;
147  triangles[vertID + 0] = map[ (*osgPoints)[ (*osgTriangles)[vertID + 0] ] ];
148  triangles[vertID + 1] = map[ (*osgPoints)[ (*osgTriangles)[vertID + 1] ] ];
149  triangles[vertID + 2] = map[ (*osgPoints)[ (*osgTriangles)[vertID + 2] ] ];
150  }
151 
152  // I needed this reconversion using osgVec3Array because the triangulator changed my positions somehow.
153  return WTriangleMesh::SPtr( new WTriangleMesh( wge::osgVec3Array( points ), triangles ) );
154 }