OpenWalnut  1.5.0dev
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 "WGEGeometryUtils.h"
33 #include "WGEUtils.h"
34 #include "WTriangleMesh.h"
35 #include "exceptions/WGEException.h"
36 
37 osg::ref_ptr< osg::Vec3Array > wge::generateCuboidQuads( const std::vector< WPosition >& corners )
38 {
39  osg::ref_ptr< osg::Vec3Array > vertices = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
40 
41  // Surfaces
42  vertices->push_back( corners[0] );
43  vertices->push_back( corners[1] );
44  vertices->push_back( corners[2] );
45  vertices->push_back( corners[3] );
46 
47  vertices->push_back( corners[1] );
48  vertices->push_back( corners[5] );
49  vertices->push_back( corners[6] );
50  vertices->push_back( corners[2] );
51 
52  vertices->push_back( corners[5] );
53  vertices->push_back( corners[4] );
54  vertices->push_back( corners[7] );
55  vertices->push_back( corners[6] );
56 
57  vertices->push_back( corners[4] );
58  vertices->push_back( corners[0] );
59  vertices->push_back( corners[3] );
60  vertices->push_back( corners[7] );
61 
62  vertices->push_back( corners[3] );
63  vertices->push_back( corners[2] );
64  vertices->push_back( corners[6] );
65  vertices->push_back( corners[7] );
66 
67  vertices->push_back( corners[0] );
68  vertices->push_back( corners[1] );
69  vertices->push_back( corners[5] );
70  vertices->push_back( corners[4] );
71  return vertices;
72 }
73 
74 osg::Vec3 wge::getQuadNormal( const WPosition& a,
75  const WPosition& b,
76  const WPosition& c )
77 {
78  WVector3d vec1 = a - b;
79  WVector3d vec2 = c - b;
80  WVector3d normal = cross( vec2, vec1 );
81  return normalize( normal );
82 }
83 
84 osg::ref_ptr< osg::Vec3Array > wge::generateCuboidQuadNormals( const std::vector< WPosition >& corners )
85 {
86  osg::ref_ptr< osg::Vec3Array > vertices = osg::ref_ptr< osg::Vec3Array >( new osg::Vec3Array );
87 
88  vertices->push_back( getQuadNormal( corners[0], corners[1], corners[2] ) );
89  vertices->push_back( getQuadNormal( corners[1], corners[5], corners[6] ) );
90  vertices->push_back( getQuadNormal( corners[5], corners[4], corners[7] ) );
91  vertices->push_back( getQuadNormal( corners[4], corners[0], corners[3] ) );
92  vertices->push_back( getQuadNormal( corners[3], corners[2], corners[6] ) );
93  vertices->push_back( getQuadNormal( corners[0], corners[1], corners[5] ) );
94  return vertices;
95 }
96 
97 WTriangleMesh::SPtr wge::triangulate( const std::vector< WPosition >& points, double transformationFactor )
98 {
99  WAssert( points.size() > 2, "The Delaunay triangulation needs at least 3 vertices!" );
100 
101  osg::ref_ptr< osg::Vec3Array > osgPoints = wge::osgVec3Array( points );
102 
103  if( transformationFactor != 0.0 )
104  {
105  // Transform the points as described in the Doxygen description of
106  // this function.
107  osg::Vec3 centroid;
108  for( std::size_t pointID = 0; pointID < osgPoints->size(); ++pointID )
109  {
110  centroid += (*osgPoints)[pointID];
111  }
112  centroid /= osgPoints->size();
113 
114  for( std::size_t pointID = 0; pointID < osgPoints->size(); ++pointID )
115  {
116  const double factor = ( (*osgPoints)[pointID].z() - centroid.z() ) * transformationFactor + 1.0;
117  (*osgPoints)[pointID].x() = ( (*osgPoints)[pointID].x() - centroid.x() ) * factor + centroid.x();
118  (*osgPoints)[pointID].y() = ( (*osgPoints)[pointID].y() - centroid.y() ) * factor + centroid.y();
119  }
120  }
121 
122  // The osg triangulator sorts the points and returns the triangles with
123  // the indizes of the sorted points. Since we don't want to change the
124  // sequence of the points, we have to save the original index of each
125  // point.
126  std::map< osg::Vec3, size_t > map;
127  for( size_t index = 0; index < osgPoints->size(); ++index )
128  {
129  map[ (*osgPoints)[index] ] = index;
130  }
131 
132  osg::ref_ptr< osgUtil::DelaunayTriangulator > triangulator( new osgUtil::DelaunayTriangulator( osgPoints ) );
133 
134  bool triangulationResult = triangulator->triangulate();
135 
136  WAssert( triangulationResult, "Something went wrong in triangulation." );
137 
138  osg::ref_ptr< const osg::DrawElementsUInt > osgTriangles( triangulator->getTriangles() );
139  size_t nbTriangles = osgTriangles->size() / 3;
140  std::vector< size_t > triangles( osgTriangles->size() );
141  for( size_t triangleID = 0; triangleID < nbTriangles; ++triangleID )
142  {
143  // Convert the new index of the osgTriangle to the original
144  // index stored in map.
145  size_t vertID = triangleID * 3;
146  triangles[vertID + 0] = map[ (*osgPoints)[ (*osgTriangles)[vertID + 0] ] ];
147  triangles[vertID + 1] = map[ (*osgPoints)[ (*osgTriangles)[vertID + 1] ] ];
148  triangles[vertID + 2] = map[ (*osgPoints)[ (*osgTriangles)[vertID + 2] ] ];
149  }
150 
151  // I needed this reconversion using osgVec3Array because the triangulator changed my positions somehow.
152  return WTriangleMesh::SPtr( new WTriangleMesh( wge::osgVec3Array( points ), triangles ) );
153 }
This only is a 3d double vector.
Triangle mesh data structure allowing for convenient access of the elements.
Definition: WTriangleMesh.h:46
std::shared_ptr< WTriangleMesh > SPtr
Shared pointer.
Definition: WTriangleMesh.h:55
osg::ref_ptr< osg::Vec3Array > generateCuboidQuadNormals(const std::vector< WPosition > &corners)
Generates for all QUADS of the Cuboid the normals in the following order:
WTriangleMesh::SPtr triangulate(const std::vector< WPosition > &points, double transformationFactor=0.0)
Calculate the Delaunay Triangulation of the given points.
osg::Vec3 getQuadNormal(const WPosition &a, const WPosition &b, const WPosition &c)
Generates for a QUAD given via 3 three points ( the fourth is not needed ) the normal.
osg::ref_ptr< osg::Vec3Array > generateCuboidQuads(const std::vector< WPosition > &corners)
Creates out of eight corner vertices QUAD vertices.
osg::ref_ptr< osg::Vec3Array > osgVec3Array(const std::vector< WPosition > &posArray)
Converts a whole vector of WPositions into an osg::Vec3Array.
Definition: WGEUtils.cpp:40