OpenWalnut  1.5.0dev
WSubdivisionValidator.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 <cmath>
26 #include <memory>
27 #include <vector>
28 
29 #include "WSubdivisionValidator.h"
30 
31 
32 namespace butterfly
33 {
35 {
37  this->m_vertexFactory = new WVertexFactory();
38  this->m_minTransformationAngle = 0.0f;
39  this->m_maxTransformationAngle = 180.0f;
40  this->m_minLenghtsQuotient = 0.0f;
41  this->m_minAmountOfMax = 0.0f;
42  this->m_minAmountOfAverage = 0.0f;
43  this->m_minSubdividedLineLength = 0.0f;
45  this->m_minNeighbourTriangleAngle = 0.0f;
46  this->m_maxNeighbourTriangleAngle = 180.0f;
48  this->m_maxAmountOfMaxForVertexJoin = 0.0f;
50 }
51 
53 {
54  // TODO(schwarzkopf): Auto-generated destructor stub
55 }
56 
57 void WSubdivisionValidator::setTriangleMesh( std::shared_ptr< WTriangleMesh > processedMesh, WVertexFactory* vertexFactory )
58 {
59  this->m_processedMesh = processedMesh;
60  this->m_vertexFactory = vertexFactory;
61 }
63 {
64  for ( size_t vertexID = 0; vertexID < m_vertexFactory->getVertexCount(); vertexID++ )
65  {
66  float maxDistance = 0.0f;
67  float summedDistance = 0.0f;
68 
69  WVertexProperty* property = m_vertexFactory->getProperty( vertexID );
70  size_t neighbourCount = property->getValence();
71  for ( size_t neighbour = 0; neighbour < neighbourCount; neighbour++ )
72  {
73  size_t neighbourID = property->getStencilNeighbourID( neighbour );
74  osg::Vec3 point1 = m_processedMesh->getVertex( vertexID );
75  osg::Vec3 point2 = m_processedMesh->getVertex( neighbourID );
76  float distance = WVertexFactory::getDistance( point1, point2 );
77  maxDistance = distance>maxDistance ?distance :maxDistance;
78  summedDistance += distance;
79  }
80  property->setMaxNeighbourDistance( maxDistance );
81  property->setSumNeighbourDistance( summedDistance );
82  }
83 }
84 
85 std::shared_ptr< WTriangleMesh > WSubdivisionValidator::joinNarrowVertices(
86  std::shared_ptr< WTriangleMesh > inputMesh )
87 {
88  if ( m_maxAmountOfMaxForVertexJoin > 0.0f )
89  {
90  size_t vertCount = inputMesh->vertSize();
91  std::shared_ptr< WTriangleMesh > outputMesh( new WTriangleMesh( 0, 0 ) );
92  size_t triCount = inputMesh->triangleSize();
93  std::vector<osg::Vec3> vertices;
94  vertices.reserve( vertCount );
95  vertices.resize( vertCount );
96  for ( size_t idx = 0; idx < vertCount; idx++ )
97  vertices[idx] = osg::Vec3( inputMesh->getVertex( idx ) );
98  std::vector<size_t> triangles;
99  triangles.reserve( triCount * 3 );
100  triangles.resize( triCount * 3 );
101  for (size_t triangle = 0; triangle < triCount; triangle++ )
102  {
103  triangles[triangle * 3 + 0] = inputMesh->getTriVertId0( triangle );
104  triangles[triangle * 3 + 1] = inputMesh->getTriVertId1( triangle );
105  triangles[triangle * 3 + 2] = inputMesh->getTriVertId2( triangle );
106  }
107  for ( size_t triangle = 0; triangle < triCount; triangle++ )
108  {
109  size_t id0 = triangles[triangle * 3 + 0];
110  size_t id1 = triangles[triangle * 3 + 1];
111  size_t id2 = triangles[triangle * 3 + 2];
112  for ( size_t orientation = 0; orientation < 3 && id0 != id1 && id1 != id2 && id2 != id0; orientation++)
113  {
114  size_t tmp = id0;
115  id0 = id1;
116  id1 = id2;
117  id2 = tmp;
118 
119  float distanceA = WVertexFactory::getDistance( vertices[id0], vertices[id1] );
120  float distanceB = WVertexFactory::getDistance( vertices[id0], vertices[id2] );
121  float distanceC = WVertexFactory::getDistance( vertices[id1], vertices[id2] );
122  float distanceCquot = distanceC/m_maxAmountOfMaxForVertexJoin;
123  if ((distanceCquot < distanceA || distanceCquot < distanceB) && distanceC < distanceA && distanceC < distanceB )
124  {
125  size_t vert1 = id1 <= id2 ?id1 :id2;
126  size_t vert2 = id1 <= id2 ?id2 :id1;
127 
128  vertices[vert1] = WVertexFactory::add( osg::Vec3( 0, 0, 0 ), vertices[vert1], 0.5f );
129  vertices[vert1] = WVertexFactory::add( vertices[vert1], vertices[vert2], 0.5f );
130  vertices[vert2] = vertices[vert1];
131  WVertexProperty* prop1 = m_vertexFactory->getProperty( vert1 );
132  WVertexProperty* prop2 = m_vertexFactory->getProperty( vert2 );
133  vector<size_t> attachedTriangles = prop2->getAttachedTriangles();
134  for ( size_t attachedTri = 0; attachedTri < attachedTriangles.size(); attachedTri++ )
135  {
136  size_t currentTriangle = attachedTriangles[attachedTri];
137  prop1->attachTriangle( currentTriangle );
138  prop2->detachTriangle( currentTriangle );
139  for ( size_t edge = 0; edge < 3; edge++ )
140  if ( triangles[currentTriangle * 3 + edge] == vert2 )
141  triangles[currentTriangle * 3 + edge] = vert1;
142  }
143  id1 = id1 <= id2 ?id1 :id2;
144  id2 = id1 <= id2 ?id1 :id2;
145  }
146  }
147  }
148  for ( size_t vertexID = 0; vertexID < vertCount; vertexID++ )
149  {
150  outputMesh->addVertex( vertices[vertexID] );
151 
152  vector<size_t> tris = m_vertexFactory->getProperty( vertexID )->getAttachedTriangles();
153  }
154  for ( size_t idx = 0; idx < triCount; idx++ )
155  outputMesh->addTriangle( triangles[idx * 3 + 0], triangles[idx * 3 + 1], triangles[idx * 3 + 2] );
156 
157  return outputMesh;
158  }
159  return inputMesh;
160 }
161 std::shared_ptr< WTriangleMesh > WSubdivisionValidator::flipTrianglesAtLowAngles(
162  std::shared_ptr< WTriangleMesh > inputMesh )
163 {
165  {
166  size_t vertCount = inputMesh->vertSize();
167  std::shared_ptr< WTriangleMesh > outputMesh( new WTriangleMesh( 0, 0 ) );
168  for ( size_t vertID = 0; vertID < vertCount; vertID++)
169  outputMesh->addVertex( inputMesh->getVertex( vertID ) );
170 
171  size_t triCount = inputMesh->triangleSize();
172  std::vector<bool> isProcessed;
173  isProcessed.reserve( triCount );
174  isProcessed.resize( triCount );
175  std::vector<size_t> triangles;
176  triangles.reserve( triCount * 3 );
177  triangles.resize( triCount * 3 );
178  for ( size_t triangle = 0; triangle < triCount; triangle++ )
179  {
180  isProcessed[triangle] = false;
181  triangles[triangle * 3 + 0] = inputMesh->getTriVertId0( triangle );
182  triangles[triangle * 3 + 1] = inputMesh->getTriVertId1( triangle );
183  triangles[triangle * 3 + 2] = inputMesh->getTriVertId2( triangle );
184  }
185  for (size_t triangle = 0; triangle < triCount; triangle++ )
186  {
187  size_t id0 = triangles[ triangle * 3 + 0 ];
188  size_t id1 = triangles[ triangle * 3 + 1 ];
189  size_t id2 = triangles[ triangle * 3 + 2 ];
190  for ( size_t index = 0; index < 3; index++ )
191  {
192  size_t tmp = id0;
193  id0 = id1;
194  id1 = id2;
195  id2 = tmp;
196 
197  std::vector<size_t> neighbours = m_vertexFactory->getAttachedTriangleIDs( triangle, id0, id1 );
198  if ( neighbours.size() == 1 && !isProcessed[triangle] )
199  {
200  size_t triangle2 = neighbours[0];
201  size_t vecID3OtherTriangle = m_vertexFactory->get3rdVertexID( triangle2, id0, id1 );
202 
203  osg::Vec3 point0 = m_processedMesh->getVertex( id0 );
204  osg::Vec3 point1 = m_processedMesh->getVertex( id1 );
205  osg::Vec3 point2 = m_processedMesh->getVertex( id2 );
206  osg::Vec3 point2other = m_processedMesh->getVertex( vecID3OtherTriangle );
207  float lengthA1 = WVertexFactory::getDistance( point0, point2 );
208  float lengthB1 = WVertexFactory::getDistance( point1, point2 );
209  float lengthA2 = WVertexFactory::getDistance( point0, point2other );
210  float lengthB2 = WVertexFactory::getDistance( point1, point2other );
211  float lengthC = WVertexFactory::getDistance( point0, point1 );
212  float lengthD = WVertexFactory::getDistance( point2, point2other );
213  float alpha1 = getAlphaLawOfCosines( lengthB1, lengthA1, lengthC );
214  float beta1 = getAlphaLawOfCosines( lengthA1, lengthB1, lengthC );
215  float alpha2 = getAlphaLawOfCosines( lengthB1, lengthA1, lengthC );
216  float beta2 = getAlphaLawOfCosines( lengthA1, lengthB1, lengthC );
217  float gammaA1 = getAlphaLawOfCosines( lengthA2, lengthA1, lengthD );
218  float gammaB1 = getAlphaLawOfCosines( lengthB2, lengthB1, lengthD );
219 
222  && 180.0f-gammaA1 - alpha1 - alpha2 >= m_maxNeighbourTriangleAngleTriangleFlip
223  && 180.0f-gammaB1 - beta1 - beta2 >= m_maxNeighbourTriangleAngleTriangleFlip
224  && alpha1 + alpha2 < 180.0f && beta1 + beta2 < 180.0f
226  && !isProcessed[triangle] && !isProcessed[triangle2] )
227  {
228  m_vertexFactory->getProperty( id0 )->detachTriangle( triangle2 );
229  m_vertexFactory->getProperty( id1 )->detachTriangle( triangle );
230  m_vertexFactory->getProperty( id2 )->attachTriangle( triangle2 );
231  m_vertexFactory->getProperty( vecID3OtherTriangle )->attachTriangle( triangle );
232 
233  for ( size_t idx = 0; idx < 3; idx++ )
234  {
235  if ( triangles[triangle * 3 + idx] == id1 )
236  triangles[triangle * 3 + idx] = vecID3OtherTriangle;
237  if ( triangles[triangle2 * 3 + idx] == id0 )
238  triangles[triangle2 * 3 + idx] = id2;
239  }
240 
241  isProcessed[triangle] = true;
242  isProcessed[triangle2] = true;
243  }
244  }
245  }
246  }
247  for ( size_t idx = 0; idx < triCount; idx++ )
248  outputMesh->addTriangle( triangles[idx * 3 + 0], triangles[idx * 3 + 1], triangles[idx * 3 + 2] );
249 
250  return outputMesh;
251  }
252  return inputMesh;
253 }
254 
255 osg::Vec3 WSubdivisionValidator::getValidatedSubdivision( size_t vertID1, size_t vertID2, osg::Vec3 newVert )
256 {
257  if ( m_minNeighbourTriangleAngle < 90.0f )
258  {
259  float minAngle = getMinTrianglesAngle( vertID1, vertID2, false );
260  if ( minAngle < m_minNeighbourTriangleAngle )
261  {
262  float weight = minAngle/m_minNeighbourTriangleAngle;
263  newVert = WVertexFactory::add( osg::Vec3( 0, 0, 0 ), newVert, weight );
264  newVert = WVertexFactory::add( newVert, m_processedMesh->getVertex( vertID1 ), 0.5f * ( 1-weight ) );
265  newVert = WVertexFactory::add( newVert, m_processedMesh->getVertex( vertID2 ), 0.5f * ( 1-weight ) );
266  }
267  }
268  return newVert;
269 }
270 bool WSubdivisionValidator::isValidSubdivision( size_t vertID1, size_t vertID2, osg::Vec3 vert3 )
271 {
272  if ( vertID1 == vertID2 )
273  return false;
274 
275  osg::Vec3 vert1 = m_processedMesh->getVertex( vertID1 );
276  osg::Vec3 vert2 = m_processedMesh->getVertex( vertID2 );
277  float lengthA = WVertexFactory::getDistance( vert1, vert3 );
278  float lengthB = WVertexFactory::getDistance( vert2, vert3 );
279  float lengthC = WVertexFactory::getDistance( vert1, vert2 );
280  if ( !isValidMinAmountOfMax( vertID1, vertID2, lengthC ) )
281  return false;
282 
283  if ( !isValidMinAmountOfAverage( vertID1, vertID2, lengthC ) )
284  return false;
285 
286  if ( !isValidMinLengthsQuotient( lengthA, lengthB ) )
287  return false;
288 
289  if ( !isValidMinTransformationAngle( lengthA, lengthB, lengthC ) )
290  return false;
291 
292  if ( !isValidMaxTransformationAngle( lengthA, lengthB, lengthC ) )
293  return false;
294 
295  if ( !isValidMinSubdividedLineLength( lengthC ) )
296  return false;
297 
298  if ( !isValidMaxNeighbourTriangleAngle( vertID1, vertID2, lengthC ) )
299  return false;
300 
301  return true;
302 }
303 bool WSubdivisionValidator::isValidMinAmountOfMax( size_t vertID1, size_t vertID2, float lengthC )
304 {
305  if ( this->m_minAmountOfMax == 0.0f )
306  return true;
307  float vertex1max = m_vertexFactory->getProperty( vertID1 )->getMaxNeighbourDistance();
308  float vertex2max = m_vertexFactory->getProperty( vertID2 )->getMaxNeighbourDistance();
309  return lengthC >= vertex1max*m_minAmountOfMax
310  && lengthC >= vertex2max*m_minAmountOfMax;
311 }
312 bool WSubdivisionValidator::isValidMinAmountOfAverage( size_t vertID1, size_t vertID2, float lengthC )
313 {
314  if ( this->m_minAmountOfAverage == 0.0f )
315  return true;
316  WVertexProperty* vertex1 = m_vertexFactory->getProperty( vertID1 );
317  WVertexProperty* vertex2 = m_vertexFactory->getProperty( vertID2 );
318  float vertex1Valence = vertex1->getValence();
319  float vertex2Valence = vertex2->getValence();
320  float vertex1Sum = vertex1->getSumNeighbourDistance();
321  float vertex2Sum = vertex2->getSumNeighbourDistance();
322  float average = vertex1Sum + vertex2Sum - 2.0f * lengthC;
323  average /= vertex1Valence + vertex2Valence - 2.0f;
324  return average * m_minAmountOfAverage <= lengthC;
325 }
326 bool WSubdivisionValidator::isValidMinTransformationAngle( float lengthA, float lengthB, float lengthC )
327 {
328  if ( m_minTransformationAngle <= 0.0f )
329  return true;
330 
331  if ( getAlphaLawOfCosines( lengthA, lengthB, lengthC) >= m_minTransformationAngle )
332  return true;
333 
334  if ( getAlphaLawOfCosines( lengthB, lengthA, lengthC) >= m_minTransformationAngle )
335  return true;
336 
337  return false;
338 }
339 bool WSubdivisionValidator::isValidMaxTransformationAngle( float lengthA, float lengthB, float lengthC )
340 {
341  if ( m_maxTransformationAngle >= 180.0f )
342  return true;
343 
344  if ( getAlphaLawOfCosines( lengthA, lengthB, lengthC) >= m_maxTransformationAngle )
345  return false;
346 
347  if ( getAlphaLawOfCosines( lengthB, lengthA, lengthC) >= m_maxTransformationAngle )
348  return false;
349 
350  return true;
351 }
352 bool WSubdivisionValidator::isValidMinLengthsQuotient( float lengthA, float lengthB )
353 {
354  if ( m_minLenghtsQuotient <= 0 )
355  return true;
356 
357  return lengthA / lengthB >= m_minLenghtsQuotient && lengthB / lengthA >= m_minLenghtsQuotient;
358 }
360 {
361  if ( m_minSubdividedLineLength <= 0 )
362  return true;
363 
364  return lengthC >= m_minSubdividedLineLength;
365 }
366 bool WSubdivisionValidator::isValidMaxNeighbourTriangleAngle( size_t vertID1, size_t vertID2, float lengthC )
367 {
368  float maxAngle = m_maxNeighbourTriangleAngle;
370  if ( m_maxNeighbourTriangleAngle >= 180.0f )
371  return true;
372 
373  std::vector<size_t> sharedTriangleIDs = m_vertexFactory->getAttachedTriangleIDs( -1, vertID1, vertID2 );
374  if ( sharedTriangleIDs.size() == 0 )
375  return false;
376 
377  osg::Vec3 vertex1 = m_processedMesh->getVertex( vertID1 );
378  osg::Vec3 vertex2 = m_processedMesh->getVertex( vertID2 );
379  for ( size_t vertIndex = 0; vertIndex < sharedTriangleIDs.size(); vertIndex++ )
380  {
381  size_t triangleID = sharedTriangleIDs[ vertIndex ];
382  size_t vertID3 = m_vertexFactory->get3rdVertexID( triangleID, vertID1, vertID2 );
383  osg::Vec3 vertex3 = m_processedMesh->getVertex( vertID3 );
384  float lengthA = WVertexFactory::getDistance( vertex1, vertex3 );
385  float lengthB = WVertexFactory::getDistance( vertex2, vertex3 );
386  float angleA = getAlphaLawOfCosines( lengthB, lengthA, lengthC );
387  float angleB = getAlphaLawOfCosines( lengthA, lengthB, lengthC );
388  if ( ( angleA > maxAngle && lengthA > lengthC * maxRatio ) ||
389  ( angleB > maxAngle && lengthB > lengthC * maxRatio ) )
390  return false;
391  }
392  return true;
393 }
394 float WSubdivisionValidator::getMinTrianglesAngle( size_t vertID1, size_t vertID2, bool maxInTriangle )
395 {
396  std::vector<size_t> sharedTriangleIDs = m_vertexFactory->getAttachedTriangleIDs( -1, vertID1, vertID2 );
397  size_t size = sharedTriangleIDs.size();
398  float minTriangleAngle = 90.0f;
399  if ( size == 0 )
400  return false;
401 
402  osg::Vec3 vertex1 = m_processedMesh->getVertex( vertID1 );
403  osg::Vec3 vertex2 = m_processedMesh->getVertex( vertID2 );
404  for ( size_t vertIndex = 0; vertIndex < size; vertIndex++ )
405  {
406  size_t triangleID = sharedTriangleIDs[ vertIndex ];
407  size_t vertID3 = m_vertexFactory->get3rdVertexID( triangleID, vertID1, vertID2 );
408  osg::Vec3 vertex3 = m_processedMesh->getVertex( vertID3 );
409  float lengthA = WVertexFactory::getDistance( vertex1, vertex3 );
410  float lengthB = WVertexFactory::getDistance( vertex2, vertex3 );
411  float lengthC = WVertexFactory::getDistance( vertex1, vertex2 );
412  float angle1 = getAlphaLawOfCosines( lengthA, lengthB, lengthC );
413  float angle2 = getAlphaLawOfCosines( lengthB, lengthA, lengthC );
414  angle1 = ( angle1 < angle2 ) != maxInTriangle ?angle1 :angle2;
415  if ( angle1 < minTriangleAngle )
416  minTriangleAngle = angle1;
417  }
418  return minTriangleAngle;
419 }
420 
421 /**
422  * a^2=b^2+c^2-2bc cos alpha
423  */
424 float WSubdivisionValidator::getAlphaLawOfCosines( float lengthA, float lengthB, float lengthC )
425 {
426  float angle = pow( lengthA, 2.0f ) - pow( lengthB, 2.0f ) - pow( lengthC, 2.0f );
427  angle /= -2 * lengthB * lengthC;
428  if ( angle >= 1.0f )
429  return 0.0f;
430 
431  if ( angle <= -1.0f )
432  return 180.0f;
433 
434  return acos( angle ) / M_PI * 180.0f;
435 }
436 void WSubdivisionValidator::setMinTransformationAngle( float minTransformationAngle )
437 {
438  this->m_minTransformationAngle = minTransformationAngle;
439 }
440 void WSubdivisionValidator::setMaxTransformationAngle( float maxTransformationAngle )
441 {
442  this->m_maxTransformationAngle = maxTransformationAngle;
443 }
444 void WSubdivisionValidator::setMinLenghtsQuotient( float minLenghtsQuotient )
445 {
446  this->m_minLenghtsQuotient = minLenghtsQuotient;
447 }
448 void WSubdivisionValidator::setMinAmountOfMax( float minAmountOfMax )
449 {
450  this->m_minAmountOfMax = minAmountOfMax;
451 }
452 void WSubdivisionValidator::setMinAmountOfAverage( float minAmountOfAverage )
453 {
454  this->m_minAmountOfAverage = minAmountOfAverage;
455 }
457 {
458  return this->m_minSubdividedLineLength;
459 }
460 void WSubdivisionValidator::setMinSubdividedLineLength( float minSubdividedLineLength )
461 {
462  this->m_minSubdividedLineLength = minSubdividedLineLength;
463 }
465 {
467 }
469  float minSubdividedLineLengthMultiplierPerIteration )
470 {
471  this->m_minSubdividedLineLengthMultiplierPerIteration = minSubdividedLineLengthMultiplierPerIteration;
472 }
473 void WSubdivisionValidator::setMinMeighbourTriangleAngle( float minNeighbourTriangleAngle )
474 {
475  this->m_minNeighbourTriangleAngle = minNeighbourTriangleAngle;
476 }
477 void WSubdivisionValidator::setMaxNeighbourTriangleAngle( float maxNeighbourTriangleAngle,
478  float maxNeighbourTriangleAngleLengthRatio )
479 {
480  this->m_maxNeighbourTriangleAngle = maxNeighbourTriangleAngle;
481  this->m_maxNeighbourTriangleAngleLengthRatio = maxNeighbourTriangleAngleLengthRatio;
482 }
483 void WSubdivisionValidator::setMaxAmountOfMaxForVertexJoin( float maxAmountOfMaxForVertexJoin )
484 {
485  this->m_maxAmountOfMaxForVertexJoin = maxAmountOfMaxForVertexJoin;
486 }
487 void WSubdivisionValidator::setMaxNeighbourTriangleAngleTriangleFlip( float maxNeighbourTriangleAngleTriangleFlip )
488 {
489  this->m_maxNeighbourTriangleAngleTriangleFlip = maxNeighbourTriangleAngleTriangleFlip;
490 }
491 void WSubdivisionValidator::subdivideTriangle( size_t vertID0, size_t vertID1, size_t vertID2 )
492 {
493  WNewVertex* new0_1prop = m_vertexFactory->getNewVertexProperty( vertID0, vertID1 );
494  WNewVertex* new0_2prop = m_vertexFactory->getNewVertexProperty( vertID0, vertID2 );
495  WNewVertex* new1_2prop = m_vertexFactory->getNewVertexProperty( vertID1, vertID2 );
496  size_t new0_1id = new0_1prop->getNewVertexID();
497  size_t new0_2id = new0_2prop->getNewVertexID();
498  size_t new1_2id = new1_2prop->getNewVertexID();
499  bool new0_1valid = new0_1prop->isValid();
500  bool new0_2valid = new0_2prop->isValid();
501  bool new1_2valid = new1_2prop->isValid();
502  size_t validSum = ( new0_1valid ?1 :0 ) + ( new0_2valid ?1 :0 ) + ( new1_2valid ?1 :0 );
503  size_t validPos = ( new0_1valid ?4 :0 ) + ( new0_2valid ?2 :0 ) + ( new1_2valid ?1 :0 );
504 
505  if ( validPos == 1 || validPos == 5 )
506  {
507  size_t tmp = vertID0;
508  vertID0 = vertID1;
509  vertID1 = vertID2;
510  vertID2 = tmp;
511  new0_2id = new0_1id;
512  new0_1id = new1_2id;
513  }
514  if ( validPos == 2 || validPos == 3 )
515  {
516  size_t tmp = vertID0;
517  vertID0 = vertID2;
518  vertID2 = vertID1;
519  vertID1 = tmp;
520  new0_1id = new0_2id;
521  new0_2id = new1_2id;
522  }
523 
524  switch( validSum )
525  {
526  case 0:
527  m_processedMesh->addTriangle( vertID0, vertID1, vertID2 );
528  break;
529  case 1:
530  subdivideTriangleValidSum1( vertID0, vertID1, vertID2, new0_1id );
531  break;
532  case 2:
533  subdivideTriangleValidSum2( vertID0, vertID1, vertID2, new0_1id, new0_2id );
534  break;
535  default:
536  subdivideTriangleValidSum3( vertID0, vertID1, vertID2, new0_1id, new0_2id, new1_2id );
537  }
538 }
539 void WSubdivisionValidator::subdivideTriangleValidSum1( size_t vertID0, size_t vertID1, size_t vertID2, size_t new0_1id )
540 {
541  m_processedMesh->addTriangle( vertID0, new0_1id, vertID2 );
542  m_processedMesh->addTriangle( new0_1id, vertID1, vertID2 );
543 }
545  size_t vertID0, size_t vertID1, size_t vertID2, size_t new0_1id, size_t new0_2id )
546 {
547  m_processedMesh->addTriangle( vertID0, new0_1id, new0_2id );
548  float distance1to0_2 = WVertexFactory::getDistance( m_processedMesh->getVertex( vertID1 ), m_processedMesh->getVertex( new0_2id ) );
549  float distance2to0_1 = WVertexFactory::getDistance( m_processedMesh->getVertex( vertID2 ), m_processedMesh->getVertex( new0_1id ) );
550  if ( distance1to0_2 < distance2to0_1 )
551  {
552  m_processedMesh->addTriangle( new0_1id, vertID1, new0_2id );
553  m_processedMesh->addTriangle( vertID1, vertID2, new0_2id );
554  }
555  else
556  {
557  m_processedMesh->addTriangle( new0_1id, vertID2, new0_2id );
558  m_processedMesh->addTriangle( vertID1, vertID2, new0_1id );
559  }
560 }
561 void WSubdivisionValidator::subdivideTriangleValidSum3( size_t vertID0, size_t vertID1, size_t vertID2,
562  size_t new0_1id, size_t new0_2id, size_t new1_2id )
563 {
564  m_processedMesh->addTriangle( vertID0, new0_1id, new0_2id );
565  m_processedMesh->addTriangle( vertID1, new1_2id, new0_1id );
566  m_processedMesh->addTriangle( vertID2, new0_2id, new1_2id );
567  m_processedMesh->addTriangle( new0_1id, new1_2id, new0_2id );
568 }
569 } /* namespace butterfly */
Triangle mesh data structure allowing for convenient access of the elements.
Definition: WTriangleMesh.h:46
Object that contains all necessary properties of a vertex necessary for a sufficient analysis.
vector< size_t > getAttachedTriangles()
Get all triangle IDs attached to the current vertex.
float getMaxNeighbourDistance()
Returns the maximal neighbor distance within the current vertex.
void attachTriangle(size_t triangleID)
Registers a triangle to the current vertex.
size_t getValence()
Returns the Neighbor vertex count of the current vertex.
void detachTriangle(size_t triangleID)
Unregisters a triangle to the current vertex.
float getSumNeighbourDistance()
Returns summed neighbor distance within the current vertex.
Depicts a point that is subdivided on a line between two vertices.
Definition: WNewVertex.h:40
size_t getNewVertexID()
Returns the proposed ID of that new vertex.
Definition: WNewVertex.cpp:43
bool isValid()
Returns whether the new vertex is marked to be valid for the butterfly subdivison of a line between t...
Definition: WNewVertex.cpp:60
bool isValidMinAmountOfMax(size_t vertID1, size_t vertID2, float lengthC)
Subdivision is valid if the subdivided line is at least as long as the longest line to a neighbor mul...
bool isValidSubdivision(size_t vertID1, size_t vertID2, osg::Vec3 newVert)
This function checks a subdivided line between two vertices for correctness.
bool isValidMinLengthsQuotient(float lengthA, float lengthB)
Regards the lengths from the new subdivided new vertex.
std::shared_ptr< WTriangleMesh > m_processedMesh
Associated triangle mesh for validation instances.
float m_maxAmountOfMaxForVertexJoin
The Factor for comparison to the maximal length of a triangle.
float m_minLenghtsQuotient
Maximum factor which the following lines should differ to show a valid subdivision.
void setMinMeighbourTriangleAngle(float minNeighbourTriangleAngle)
Sets the Minimal allowed angle between two Subdivided line ends.
float getMinSubdividedLineLengthMultiplierPerIteration()
Gets the factor where the minimal subdivided line length is multiplied by in each Subdivision iterati...
void setMinSubdividedLineLength(float minSubdividedLineLength)
Sets the minimal subdividable line length.
osg::Vec3 getValidatedSubdivision(size_t vertID1, size_t vertID2, osg::Vec3 interpolatedVertex)
Corrects Coordinates if they are determined to be invalid using validation settings.
void subdivideTriangle(size_t vertID0, size_t vertID1, size_t vertID2)
Subdivides the triangle at three vertex IDs regarding the not subdividable new vertices at lines betw...
void setMinTransformationAngle(float minTransformationAngle)
Sets up the angle setting which both angles at the subdivided line ends should be at least as big as ...
void setMinAmountOfMax(float minAmountOfMax)
Sets the factor for multiplying the maximal distance to a neighbour within the Butterfly stencil.
std::shared_ptr< WTriangleMesh > joinNarrowVertices(std::shared_ptr< WTriangleMesh > inputMesh)
Joins Vertices where a triangle side is smaller than the longest one multiplied by a factor.
float m_minSubdividedLineLength
The minimal subdividable line length.
void subdivideTriangleValidSum2(size_t vertID0, size_t vertID1, size_t vertID2, size_t new0_1id, size_t new0_2id)
Subdivides a triangle with two valid subdividable new vertices: Vertices should be rotated so that th...
void setMinAmountOfAverage(float minAmountOfAverage)
Sets the factor for multiplying the average distance to a neighbour within the Butterfly stencil.
bool isValidMaxTransformationAngle(float lengthA, float lengthB, float lengthC)
Checks whether both angles at the subdivided line ends are not bigger than a defined maximal value.
void setMaxNeighbourTriangleAngle(float maxNeighbourTriangleAngle, float maxNeighbourTriangleAngleLengthRatio)
Sets settings of the further feature: A subdivision is marked as invalid if the angle between any nei...
void setMinLenghtsQuotient(float minLenghtsQuotient)
Sets the maximum factor which the following lines should differ to show a valid subdivision.
std::shared_ptr< WTriangleMesh > flipTrianglesAtLowAngles(std::shared_ptr< WTriangleMesh > inputMesh)
Searchs for all triangles which has two angles below a preset value.
WVertexFactory * m_vertexFactory
Associated analysis data of the the triangle mesh to be validated.
void subdivideTriangleValidSum1(size_t vertID0, size_t vertID1, size_t vertID2, size_t new0_1id)
Subdivides a triangle with one valid subdividable new vertex: Vertices should be rotated so that the ...
float m_maxNeighbourTriangleAngleLengthRatio
This settings extends m_maxNeighbourTriangleAngle; If the line length is smaller than the subdividabl...
float m_minSubdividedLineLengthMultiplierPerIteration
The factor where the minimal subdivided line length is multiplied by in each Subdivision iteration st...
WSubdivisionValidator()
Creates the Butterfly subdivision validation instance.
void setMinSubdividedLineLengthMultiplierPerIteration(float minSubdividedLineLengthMultiplierPerIteration)
Sets the factor where the minimal subdivided line length is multiplied by in each Subdivision iterati...
float getMinSubdividedLineLength()
Gets the minimal subdividable line length.
void generateStatisticalInformation()
Generating statistical information of the triangle mesh.
float m_maxNeighbourTriangleAngleTriangleFlip
The Minimal allowed angle which fits in both vertices at a subdividable line end.
void setTriangleMesh(std::shared_ptr< WTriangleMesh > processedMesh, WVertexFactory *vertexFactory)
Assign analyzable triangle mesh.
bool isValidMinAmountOfAverage(size_t vertID1, size_t vertID2, float lengthC)
Subdivision is valid if the subdivided line is at least as long as the average line to a neighbor mul...
float m_minAmountOfAverage
Factor for multiplying the average distance to a neighbour within the Butterfly stencil.
void setMaxNeighbourTriangleAngleTriangleFlip(float maxNeighbourTriangleAngleTriangleFlip)
Sets the Minimal allowed angle which fits in both vertices at a subdividable line end.
static float getAlphaLawOfCosines(float lengthA, float lengthB, float lengthC)
The law of cosines.
float m_maxNeighbourTriangleAngle
A subdivision is marked as invalid if the angle between any neighbor triangle line is above that angl...
void setMaxTransformationAngle(float maxTransformationAngle)
Sets up the angle setting which both angles at the subdivided line ends should be not bigger than thi...
float m_minAmountOfMax
Factor for multiplying the maximal distance to a neighbour within the Butterfly stencil.
float getMinTrianglesAngle(size_t vertID1, size_t vertID2, bool maxInTriangle)
Get the minimal triangle angle at the two vertices searching all triangles connected to that points.
bool isValidMinSubdividedLineLength(float lengthC)
Checks whether a subdividable line length is not longer than a set up length setting.
virtual ~WSubdivisionValidator()
Destroys the Butterfly subdivision validation instance.
float m_maxTransformationAngle
Angle setting which both angles at the subdivided line ends should be not bigger than this value.
void setMaxAmountOfMaxForVertexJoin(float maxAmountOfMaxForVertexJoin)
Sets the Factor for comparison to the maximal length of a triangle.
bool isValidMaxNeighbourTriangleAngle(size_t vertID1, size_t vertID2, float lengthC)
Checks whether .the angle between the subdividable line and any other line of all neighbor triangles ...
float m_minNeighbourTriangleAngle
The Minimal allowed angle between two Subdivided line ends.
float m_minTransformationAngle
Angle setting which both angles at the subdivided line ends should be at least as big as this value.
bool isValidMinTransformationAngle(float lengthA, float lengthB, float lengthC)
Checks whether both angles at the subdivided line ends are at least as big as a defined minimal value...
void subdivideTriangleValidSum3(size_t vertID0, size_t vertID1, size_t vertID2, size_t new0_1id, size_t new0_2id, size_t new1_2id)
Subdivides a triangle with all valid subdividable new vertices.
Class that manages all vertex properties.
WVertexProperty * getProperty(size_t vertexID)
Get properties of a vertex.
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.
static osg::Vec3 add(osg::Vec3 base, osg::Vec3 sum, float factor)
Adding a sum multiplied by a factor to the base number.
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.