OpenWalnut  1.5.0dev
WVertexFactory.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2013 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 <memory>
26 #include <vector>
27 
28 #include "WVertexFactory.h"
29 
30 
31 namespace butterfly
32 {
34  {
35  m_vertexCount = 0;
36  m_triangleCount = 0;
37  }
38 
39  WVertexFactory::WVertexFactory( std::shared_ptr< WTriangleMesh > triangleMesh )
40  {
41  this->m_triangleMesh = triangleMesh;
42  m_vertexCount = 0;
43  m_triangleCount = 0;
44  }
45 
47  {
48  //TODO(schwarzkopf): Memory is still not freed
49  for ( size_t index = 0; index < m_vertProp.size(); index++ )
50  m_vertProp[index]->~WVertexProperty();
51 
52  m_vertProp.resize( 0 );
53  m_vertProp.reserve( 0 );
54  }
55  void WVertexFactory::setTriangleMesh( std::shared_ptr< WTriangleMesh > triangleMesh )
56  {
57  this->m_triangleMesh = triangleMesh;
58  }
59 
60  void WVertexFactory::resize( size_t finalSize )
61  {
62  m_vertexCount = finalSize;
63  size_t size = this->m_vertProp.size();
64  if ( finalSize >= size )
65  {
66  this->m_vertProp.reserve( finalSize * 3 / 2 );
67  this->m_vertProp.resize( finalSize * 3 / 2 );
68 
69  for ( size_t vertID = size; vertID < finalSize * 3 / 2; vertID++ )
70  this->m_vertProp[vertID] = new WVertexProperty();
71  }
72  }
73 
74  void WVertexFactory::registerTriangle( size_t vertexID, size_t triangleID )
75  {
76  if ( vertexID >= m_vertexCount )
77  resize( vertexID+1 );
78 
79  this->m_vertProp[vertexID]->attachTriangle( triangleID );
80  if ( triangleID >= m_triangleCount )
81  m_triangleCount = triangleID;
82  }
83 
85  {
86  return m_vertexCount;
87  }
88 
89  vector<size_t> WVertexFactory::getAttachedTriangleIDs( size_t excludedTriangleID, size_t vert1, size_t vert2 )
90  {
91  vector<size_t> tris;
92  size_t thirdID = excludedTriangleID >= m_triangleCount ?-1
93  :get3rdVertexID( excludedTriangleID, vert1, vert2 );
94 
95  int sizeN = m_vertProp[vert1]->getTriangleCount();
96  for ( int neighbour = 0; vert1 != vert2 && neighbour < sizeN; neighbour++ )
97  {
98  size_t newTriID = m_vertProp[vert1]->getAttachedTriangles() [neighbour];
99  size_t newTriVertID = get3rdVertexID( newTriID, vert1, vert2 );
100  if( newTriID != excludedTriangleID && this->m_vertProp[vert2]->containsTriangle( newTriID )
101  && isValidTriangle( newTriID ) && thirdID != newTriVertID )
102  {
103  int size = tris.size();
104  tris.reserve( size + 1 );
105  tris.resize( size + 1 );
106  tris[size] = newTriID;
107  }
108  }
109  return tris;
110  }
111 
112  size_t WVertexFactory::get3rdVertexID( size_t triangleID, size_t vert1, size_t vert2 )
113  {
114  size_t id0 = m_triangleMesh->getTriVertId0( triangleID ),
115  id1 = m_triangleMesh->getTriVertId1( triangleID ),
116  id2 = m_triangleMesh->getTriVertId2( triangleID );
117  if ( vert1 != id0 && vert2 != id0 )
118  return id0;
119 
120  if ( vert1 != id1 && vert2 != id1 )
121  return id1;
122 
123  return id2;
124  }
125  bool WVertexFactory::newVertexExists( size_t vertID1, size_t vertID2 )
126  {
127  if( vertID1 == vertID2 )
128  return true;
129 
130  if( vertID1 > vertID2 )
131  {
132  size_t tmp = vertID1;
133  vertID1 = vertID2;
134  vertID2 = tmp;
135  }
136  return this->m_vertProp[vertID1]->newVertexExists( vertID2 );
137  }
138 
139  bool WVertexFactory::isValidTriangle( size_t triangleID )
140  {
141  size_t id0 = m_triangleMesh->getTriVertId0( triangleID );
142  size_t id1 = m_triangleMesh->getTriVertId1( triangleID );
143  size_t id2 = m_triangleMesh->getTriVertId2( triangleID );
144  return id0 != id1 && id0 != id2 && id1 != id2;
145  }
146  void WVertexFactory::attachNewVertex( size_t vertex1, size_t vertex2 )
147  {
148  if ( vertex1 == vertex2 )
149  return;
150 
151  if ( vertex1 > vertex2 )
152  {
153  size_t tmp = vertex1;
154  vertex1 = vertex2;
155  vertex2 = tmp;
156  }
157  this->m_vertProp[vertex1]->attachNewVertex( vertex2 );
158  }
159 
161  {
162  return this->m_vertProp[vertexID];
163  }
164  WNewVertex* WVertexFactory::getNewVertexProperty( size_t vertex1, size_t vertex2 )
165  {
166  if ( vertex1 == vertex2 )
167  {
168  WNewVertex* invalidPoint = new WNewVertex( vertex2 );
169  invalidPoint->setValid( false );
170  return invalidPoint;
171  }
172  if ( vertex1 > vertex2 )
173  {
174  size_t tmp = vertex1;
175  vertex1 = vertex2;
176  vertex2 = tmp;
177  }
178  return m_vertProp[vertex1]->getNewVertexProperty( vertex2 );
179  }
180  void WVertexFactory::examineStencilRange( size_t fromVertex, size_t toVertex,
181  std::shared_ptr< WProgress > progress )
182  {
183  for ( size_t vert = fromVertex; vert <= toVertex; vert++ )
184  {
185  vector<size_t> attachedTriangles = this->m_vertProp[vert]->getAttachedTriangles();
186  size_t totalTriangleCount = 0;
187  for ( size_t triangle = 0; triangle < attachedTriangles.size(); triangle++ )
188  if ( isValidTriangle( attachedTriangles[triangle] ) )
189  totalTriangleCount++;
190 
191  progress->increment( 1 );
192  size_t startTriID = 0;
193  while ( startTriID < attachedTriangles.size() && !isValidTriangle(attachedTriangles[startTriID] ) )
194  startTriID++;
195 
196  if ( startTriID < attachedTriangles.size() )
197  {
198  size_t firstTri = attachedTriangles[startTriID],
199  vertID0 = this->m_triangleMesh->getTriVertId0( firstTri ),
200  vertBound = ( vertID0 != vert ? vertID0 : this->m_triangleMesh->getTriVertId1( firstTri ) ),
201  firstVert = vertBound;
202  vector<size_t> tris = getAttachedTriangleIDs( -1, vert, firstVert );
203  bool moreThanTwo = tris.size() > 2;
204  size_t firstDirection = tris[0];
205  size_t ranTriangles = 0;
206  WVertexProperty* property = m_vertProp[vert];
207  do
208  {
209  ranTriangles++;
210  property->addStencilNeighbourIDToBack( vertBound );
211  vertBound = get3rdVertexID( tris[0], vert, vertBound );
212  tris = getAttachedTriangleIDs( tris[0], vert, vertBound );
213  } while( vertBound != firstVert && tris.size() == 1 );
214 
215  if ( vertBound != firstVert && tris.size() < 2 )
216  {
217  property->addStencilNeighbourIDToBack( vertBound );
218  vertBound = firstVert;
219  tris = getAttachedTriangleIDs( firstDirection, vert, vertBound );
220  while ( tris.size() == 1 )
221  {
222  ranTriangles++;
223  vertBound = get3rdVertexID( tris[0], vert, vertBound );
224  property->insertStencilNeighbourIDToFront( vertBound );
225  tris = getAttachedTriangleIDs( tris[0], vert, vertBound );
226  };
227  vertBound = -1;
228  }
229  if ( tris.size() > 1)
230  moreThanTwo = true;
231  if ( vertBound == firstVert && !moreThanTwo && ranTriangles == totalTriangleCount )
232  {
233  //TODO(schwarzkopf): Two different surfaces hitting in one point are still able to be calculated as such
234  this->m_vertProp[vert]->setBoundClass( 0 );
235  }
236  else
237  {
238  this->m_vertProp[vert]->setBoundClass( ( moreThanTwo || ranTriangles != totalTriangleCount ) ? 2 :1 );
239  if( !moreThanTwo && ranTriangles>totalTriangleCount )
240  m_vertProp[vert]->setBoundClass( -1 );
241  }
242  }
243  }
244  }
245  float WVertexFactory::getDistance( osg::Vec3 point1, osg::Vec3 point2 )
246  {
247  float deltaX2 = pow( point2.x() - point1.x(), 2.0f );
248  float deltaY2 = pow( point2.y() - point1.y(), 2.0f );
249  float deltaZ2 = pow( point2.z() - point1.z(), 2.0f );
250  return pow( deltaX2 + deltaY2 + deltaZ2, 0.5f );
251  }
252  osg::Vec3 WVertexFactory::add( osg::Vec3 base, osg::Vec3 summand, float factor )
253  {
254  float baseX = base.x(), baseY = base.y(), baseZ = base.z();
255  float sumX = summand.x(), sumY = summand.y(), sumZ = summand.z();
256  float coordX = baseX + sumX * factor;
257  float coordY = baseY + sumY * factor;
258  float coordZ = baseZ + sumZ * factor;
259  return osg::Vec3( coordX, coordY, coordZ );
260  }
261 
262 } /* namespace butterfly */
Object that contains all necessary properties of a vertex necessary for a sufficient analysis.
Depicts a point that is subdivided on a line between two vertices.
Definition: WNewVertex.h:40
void setValid(bool isValid)
Sets the new vertex property whether it's valid for butterfly subdivision or not.
Definition: WNewVertex.cpp:56
size_t m_triangleCount
Triangle count.
WVertexProperty * getProperty(size_t vertexID)
Get properties of a vertex.
std::vector< WVertexProperty * > m_vertProp
Vertex properties data.
std::shared_ptr< WTriangleMesh > m_triangleMesh
Assigned Triangle mesh.
bool isValidTriangle(size_t triangleID)
Examine triangle by its ID for validity.
WNewVertex * getNewVertexProperty(size_t fromID, size_t toID)
Get properties of a new vertex which subdivides a line between two vertices.
size_t getVertexCount()
Returns the Property List's vertex count.
size_t get3rdVertexID(size_t triangleID, size_t vertex1, size_t vertex2)
Returns the third vertex ID of a triangle.
void setTriangleMesh(std::shared_ptr< WTriangleMesh > triangleMesh)
Sets the WTriangleMesh.
void examineStencilRange(size_t fromVertex, size_t toVertex, std::shared_ptr< WProgress > progress)
Examines Butterfly stencils of all vertices and applies settings data to the vertex.
static osg::Vec3 add(osg::Vec3 base, osg::Vec3 sum, float factor)
Adding a sum multiplied by a factor to the base number.
void attachNewVertex(size_t fromID, size_t toID)
Registering a subdividable new vertex of an ID between two vertices.
void registerTriangle(size_t vertexID, size_t triangleID)
Registers triangle to all its vertex IDs.
static float getDistance(osg::Vec3 point1, osg::Vec3 point2)
Calculate distance between two vertices.
vector< size_t > getAttachedTriangleIDs(size_t excludedTriangleID, size_t vertex1, size_t vertex2)
Returns all Triangle IDs but the excluded attached to two particular vertices.
size_t m_vertexCount
Vertex count of the property list.
void resize(size_t count)
Resizes the Vertex property list to the wished size.
virtual ~WVertexFactory()
Destroys the vertex factory object.
bool newVertexExists(size_t fromID, size_t toID)
Returns whether properties of the subdividable new vertex between two vertices alreadey exists.
WVertexFactory()
Creates a vertex factory object.