29 #include "WSubdivisionValidator.h"
66 float maxDistance = 0.0f;
67 float summedDistance = 0.0f;
70 size_t neighbourCount =
property->
getValence();
71 for (
size_t neighbour = 0; neighbour < neighbourCount; neighbour++ )
73 size_t neighbourID =
property->getStencilNeighbourID( neighbour );
77 maxDistance = distance>maxDistance ?distance :maxDistance;
78 summedDistance += distance;
80 property->setMaxNeighbourDistance( maxDistance );
81 property->setSumNeighbourDistance( summedDistance );
86 std::shared_ptr< WTriangleMesh > inputMesh )
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++ )
103 triangles[triangle * 3 + 0] = inputMesh->getTriVertId0( triangle );
104 triangles[triangle * 3 + 1] = inputMesh->getTriVertId1( triangle );
105 triangles[triangle * 3 + 2] = inputMesh->getTriVertId2( triangle );
107 for (
size_t triangle = 0; triangle < triCount; triangle++ )
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++)
123 if ((distanceCquot < distanceA || distanceCquot < distanceB) && distanceC < distanceA && distanceC < distanceB )
125 size_t vert1 = id1 <= id2 ?id1 :id2;
126 size_t vert2 = id1 <= id2 ?id2 :id1;
130 vertices[vert2] = vertices[vert1];
134 for (
size_t attachedTri = 0; attachedTri < attachedTriangles.size(); attachedTri++ )
136 size_t currentTriangle = attachedTriangles[attachedTri];
139 for (
size_t edge = 0; edge < 3; edge++ )
140 if ( triangles[currentTriangle * 3 + edge] == vert2 )
141 triangles[currentTriangle * 3 + edge] = vert1;
143 id1 = id1 <= id2 ?id1 :id2;
144 id2 = id1 <= id2 ?id1 :id2;
148 for (
size_t vertexID = 0; vertexID < vertCount; vertexID++ )
150 outputMesh->addVertex( vertices[vertexID] );
154 for (
size_t idx = 0; idx < triCount; idx++ )
155 outputMesh->addTriangle( triangles[idx * 3 + 0], triangles[idx * 3 + 1], triangles[idx * 3 + 2] );
162 std::shared_ptr< WTriangleMesh > inputMesh )
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 ) );
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++ )
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 );
185 for (
size_t triangle = 0; triangle < triCount; triangle++ )
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++ )
198 if ( neighbours.size() == 1 && !isProcessed[triangle] )
200 size_t triangle2 = neighbours[0];
206 osg::Vec3 point2other =
m_processedMesh->getVertex( vecID3OtherTriangle );
224 && alpha1 + alpha2 < 180.0f && beta1 + beta2 < 180.0f
226 && !isProcessed[triangle] && !isProcessed[triangle2] )
233 for (
size_t idx = 0; idx < 3; idx++ )
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;
241 isProcessed[triangle] =
true;
242 isProcessed[triangle2] =
true;
247 for (
size_t idx = 0; idx < triCount; idx++ )
248 outputMesh->addTriangle( triangles[idx * 3 + 0], triangles[idx * 3 + 1], triangles[idx * 3 + 2] );
272 if ( vertID1 == vertID2 )
322 float average = vertex1Sum + vertex2Sum - 2.0f * lengthC;
323 average /= vertex1Valence + vertex2Valence - 2.0f;
374 if ( sharedTriangleIDs.size() == 0 )
379 for (
size_t vertIndex = 0; vertIndex < sharedTriangleIDs.size(); vertIndex++ )
381 size_t triangleID = sharedTriangleIDs[ vertIndex ];
388 if ( ( angleA > maxAngle && lengthA > lengthC * maxRatio ) ||
389 ( angleB > maxAngle && lengthB > lengthC * maxRatio ) )
397 size_t size = sharedTriangleIDs.size();
398 float minTriangleAngle = 90.0f;
404 for (
size_t vertIndex = 0; vertIndex < size; vertIndex++ )
406 size_t triangleID = sharedTriangleIDs[ vertIndex ];
414 angle1 = ( angle1 < angle2 ) != maxInTriangle ?angle1 :angle2;
415 if ( angle1 < minTriangleAngle )
416 minTriangleAngle = angle1;
418 return minTriangleAngle;
426 float angle = pow( lengthA, 2.0f ) - pow( lengthB, 2.0f ) - pow( lengthC, 2.0f );
427 angle /= -2 * lengthB * lengthC;
431 if ( angle <= -1.0f )
434 return acos( angle ) / M_PI * 180.0f;
469 float minSubdividedLineLengthMultiplierPerIteration )
478 float maxNeighbourTriangleAngleLengthRatio )
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 );
505 if ( validPos == 1 || validPos == 5 )
507 size_t tmp = vertID0;
514 if ( validPos == 2 || validPos == 3 )
516 size_t tmp = vertID0;
545 size_t vertID0,
size_t vertID1,
size_t vertID2,
size_t new0_1id,
size_t new0_2id )
550 if ( distance1to0_2 < distance2to0_1 )
562 size_t new0_1id,
size_t new0_2id,
size_t new1_2id )
Triangle mesh data structure allowing for convenient access of the elements.
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.
size_t getNewVertexID()
Returns the proposed ID of that new vertex.
bool isValid()
Returns whether the new vertex is marked to be valid for the butterfly subdivison of a line between t...
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.