1 #ifndef __CPM__DATASTRUCTURES__SIMPLEXMESH__HXX__
2 #define __CPM__DATASTRUCTURES__SIMPLEXMESH__HXX__
5 #include <vnl/vnl_math.h>
8 // -------------------------------------------------------------------------
9 template< typename P, unsigned int K, unsigned int D, typename T >
10 bool cpm::DataStructures::SimplexMesh< P, K, D, T >::
11 ComputeSimplexParameters(
12 const PointIdentifier& pId,
17 BarycenterVector& barycenter,
24 typedef itk::Matrix< ValueType, 4, 4 > TTetraMatrix;
26 static const ValueType _0 = ValueType( 0 );
27 static const ValueType _1 = ValueType( 1 );
28 static const ValueType _2 = ValueType( 2 );
29 static const ValueType _3 = ValueType( 3 );
30 static const ValueType _4 = ValueType( 4 );
32 // Get topological neighborhood
33 const TPrimalEdge* eA = this->FindEdge( pId );
36 const TPrimalEdge* eB = eA->GetOnext( );
39 const TPrimalEdge* eC = eB->GetOnext( );
43 // Get geometrical neighborhood
45 Q = this->GetPoint( eA->GetOrigin( ) ).GetVectorFromOrigin( );
46 A = this->GetPoint( eA->GetDestination( ) ).GetVectorFromOrigin( );
47 B = this->GetPoint( eB->GetDestination( ) ).GetVectorFromOrigin( );
48 C = this->GetPoint( eC->GetDestination( ) ).GetVectorFromOrigin( );
51 VectorType BA = B - A;
52 VectorType CA = C - A;
53 VectorType BAxCA = itk::CrossProduct( BA, CA );
54 ValueType nBAxCA = BAxCA.GetNorm( );
55 if( !( _0 < nBAxCA ) )
58 // More auxiliary values
59 VectorType QA = Q - A;
62 ValueType nBAxCA2 = nBAxCA * nBAxCA;
63 barycenter[ 2 ] = ( itk::CrossProduct( BA, QA ) * BAxCA ) / nBAxCA2;
64 barycenter[ 1 ] = ( itk::CrossProduct( QA, CA ) * BAxCA ) / nBAxCA2;
65 barycenter[ 0 ] = _1 - barycenter[ 2 ] - barycenter[ 1 ];
67 // Compute Q projection onto neighboring plane
69 ( A * barycenter[ 0 ] ) +
70 ( B * barycenter[ 1 ] ) +
71 ( C * barycenter[ 2 ] );
76 // Compute circumcircle center and radius (r)
77 VectorType CC = BA * CA.GetSquaredNorm( );
78 CC -= CA * BA.GetSquaredNorm( );
79 CC = itk::CrossProduct( BAxCA, CC );
84 // Barycenter distance
85 d = ( Qp - CC ).GetNorm( );
87 // Desired barycenter distance
88 dp = ( ( ( A + B + C ) / _3 ) - CC ).GetNorm( );
90 // Compute tetrahedron's circumsphere
92 for( unsigned int dId = 0; dId < 3; dId++ )
94 mA[ 0 ][ dId ] = A[ dId ];
95 mA[ 1 ][ dId ] = B[ dId ];
96 mA[ 2 ][ dId ] = C[ dId ];
97 mA[ 3 ][ dId ] = Q[ dId ];
105 ValueType dA = vnl_determinant( mA.GetVnlMatrix( ) );
106 if( dA > _0 ) // Tetrahedron IS NOT planar
113 mD[ 0 ][ 0 ] = A.GetSquaredNorm( );
114 mD[ 1 ][ 0 ] = B.GetSquaredNorm( );
115 mD[ 2 ][ 0 ] = C.GetSquaredNorm( );
116 mD[ 3 ][ 0 ] = Q.GetSquaredNorm( );
118 mD[ 0 ][ 1 ] = A[ 1 ];
119 mD[ 1 ][ 1 ] = B[ 1 ];
120 mD[ 2 ][ 1 ] = C[ 1 ];
121 mD[ 3 ][ 1 ] = Q[ 1 ];
122 mD[ 0 ][ 2 ] = A[ 2 ];
123 mD[ 1 ][ 2 ] = B[ 2 ];
124 mD[ 2 ][ 2 ] = C[ 2 ];
125 mD[ 3 ][ 2 ] = Q[ 2 ];
126 ValueType Dx = vnl_determinant( mD.GetVnlMatrix( ) );
128 mD[ 0 ][ 1 ] = A[ 0 ];
129 mD[ 1 ][ 1 ] = B[ 0 ];
130 mD[ 2 ][ 1 ] = C[ 0 ];
131 mD[ 3 ][ 1 ] = Q[ 0 ];
132 mD[ 0 ][ 2 ] = A[ 2 ];
133 mD[ 1 ][ 2 ] = B[ 2 ];
134 mD[ 2 ][ 2 ] = C[ 2 ];
135 mD[ 3 ][ 2 ] = Q[ 2 ];
136 ValueType Dy = vnl_determinant( mD.GetVnlMatrix( ) );
138 mD[ 0 ][ 1 ] = A[ 0 ];
139 mD[ 1 ][ 1 ] = B[ 0 ];
140 mD[ 2 ][ 1 ] = C[ 0 ];
141 mD[ 3 ][ 1 ] = Q[ 0 ];
142 mD[ 0 ][ 2 ] = A[ 1 ];
143 mD[ 1 ][ 2 ] = B[ 1 ];
144 mD[ 2 ][ 2 ] = C[ 1 ];
145 mD[ 3 ][ 2 ] = Q[ 1 ];
146 ValueType Dz = vnl_determinant( mD.GetVnlMatrix( ) );
148 mD[ 0 ][ 2 ] = A[ 2 ];
149 mD[ 1 ][ 2 ] = B[ 2 ];
150 mD[ 2 ][ 2 ] = C[ 2 ];
151 mD[ 3 ][ 2 ] = Q[ 2 ];
152 ValueType dC = vnl_determinant( mD.GetVnlMatrix( ) );
163 * WARNING: this is not necessary since sin(phi) and cos(phi)
164 * depend on R as divisor:
166 * ValueType R = ( Dx * Dx ) + ( Dy * Dy ) + ( Dz * Dz );
168 * R = ValueType( std::sqrt( double( R ) ) );
169 * R /= _2 * ValueType( std::fabs( double( dA ) ) );
174 VectorType CCCS = CC - CS;
175 ValueType cphi = CCCS.GetNorm( );
176 if( ( QA * N ) < _0 )
178 if( ( CCCS * N ) < _0 )
180 phi = ValueType( std::atan2( double( sphi ), double( cphi ) ) );
182 else // Tetrahedron IS planar
188 // -------------------------------------------------------------------------
189 template< typename P, unsigned int K, unsigned int D, typename T >
190 bool cpm::DataStructures::SimplexMesh< P, K, D, T >::
191 VerifySimplexOrder( ) const
193 if( this->m_OnextRings.size( ) == 0 )
196 typename Superclass::CntOnextRings::const_iterator rIt =
197 this->m_OnextRings.begin( );
198 unsigned int minOrder = ( *rIt )->GetOnextRingSize( );
199 unsigned int maxOrder = minOrder;
201 for( ; rIt != this->m_OnextRings.end( ); ++rIt )
203 unsigned int order = ( *rIt )->GetOnextRingSize( );
204 minOrder = ( order < minOrder )? order: minOrder;
205 maxOrder = ( maxOrder < order )? order: minOrder;
211 ( minOrder == 1 || minOrder == 2 ) &&
212 ( maxOrder == 1 || maxOrder == 2 )
215 return( ( minOrder == maxOrder ) && ( minOrder == K + 1 ) );
220 // -------------------------------------------------------------------------
221 template< typename P, unsigned int K, unsigned int D, typename T >
222 bool cpm::DataStructures::SimplexMesh< P, K, D, T >::
223 OperatorDeleteEdge( const PointIdentifier& a, const PointIdentifier& b )
225 TPrimalEdge* e0 = this->FindEdge( a, b );
229 // Name edges and faces
230 TPrimalEdge* e1 = e0->GetOnext( );
231 TPrimalEdge* e2 = e1->GetOnext( );
232 TPrimalEdge* e3 = e0->GetLnext( );
233 TPrimalEdge* e4 = e0->GetRprev( );
234 TPrimalEdge* e5 = e2->GetSym( )->GetOprev( );
235 TPrimalEdge* e6 = e4->GetLnext( );
237 CellIdentifier f0 = e0->GetLeft( );
238 CellIdentifier f1 = e0->GetRight( );
239 CellIdentifier f2 = e1->GetLeft( );
240 CellIdentifier f3 = e3->GetRight( );
242 // Disconnect edges e0, e2, e4 and origins of e1 and e3
243 TPrimalEdge::Splice( e2, e0 );
244 TPrimalEdge::Splice( e2, e1 );
245 TPrimalEdge::Splice( e5, e2->GetSym( ) );
246 TPrimalEdge::Splice( e3, e0->GetSym( ) );
247 TPrimalEdge::Splice( e3, e4 );
248 TPrimalEdge::Splice( e6, e4->GetSym( ) );
250 // Connect e1 and e3 origins
251 TPrimalEdge::Splice( e5, e1 );
252 TPrimalEdge::Splice( e6, e3 );
254 // Change e1 and e3 origins
255 e1->SetOrigin( e5->GetOrigin( ) );
256 e3->SetOrigin( e6->GetOrigin( ) );
258 // Assign face id (even if f1 is a "not face")
259 typename TPrimalEdge::Iterator eIt = e3->BeginLnext( );
260 while( eIt != e3->EndLnext( ) && *eIt != e1->GetSym( ) )
262 ( *eIt )->SetLeft( f1 );
268 this->m_OnextRings[ e5->GetOrigin( ) ] = e5;
269 this->m_OnextRings[ e6->GetOrigin( ) ] = e6;
271 // Update cells entry points
272 CellAutoPointer c1, c2, c3;
273 this->GetCell( f1, c1 );
274 this->GetCell( f2, c2 );
275 this->GetCell( f3, c3 );
277 TQuadEdgeCell* ec1 = dynamic_cast< TQuadEdgeCell* >( c1.GetPointer( ) );
278 TQuadEdgeCell* ec2 = dynamic_cast< TQuadEdgeCell* >( c2.GetPointer( ) );
279 TQuadEdgeCell* ec3 = dynamic_cast< TQuadEdgeCell* >( c3.GetPointer( ) );
281 ec1->SetEntryPrimalEdge( e3 );
282 ec2->SetEntryPrimalEdge( e1 );
283 ec3->SetEntryPrimalEdge( e3->GetSym( ) );
286 this->_DeleteFace( f0 );
288 // Delete e0 origin and destination
289 this->_DeletePoint( e0->GetOrigin( ) );
290 this->_DeletePoint( e0->GetDestination( ) );
292 // Delete edges e0, e2 and e4
293 this->_DeleteEdge( e0 );
294 this->_DeleteEdge( e2 );
295 this->_DeleteEdge( e4 );
300 // -------------------------------------------------------------------------
301 template< typename P, unsigned int K, unsigned int D, typename T >
302 cpm::DataStructures::SimplexMesh< P, K, D, T >::
308 // -------------------------------------------------------------------------
309 template< typename P, unsigned int K, unsigned int D, typename T >
310 cpm::DataStructures::SimplexMesh< P, K, D, T >::
315 // -------------------------------------------------------------------------
316 template< typename P, unsigned int K, unsigned int D, typename T >
317 typename cpm::DataStructures::SimplexMesh< P, K, D, T >::
318 VectorType cpm::DataStructures::SimplexMesh< P, K, D, T >::
319 _ComputePointNormal( const TPrimalEdge* e ) const
321 VectorType N( ValueType( 0 ) );
325 PointIdentifier iQp0 = e->GetOrigin( );
326 PointIdentifier iQp1 = e->GetDestination( );
327 PointIdentifier iQm1 = e->GetOnext( )->GetDestination( );
328 PointIdentifier iQp2 = e->GetSym( )->GetOnext( )->GetDestination( );
329 PointIdentifier iQm2 =
330 e->GetOnext( )->GetSym( )->GetOnext( )->GetDestination( );
332 VectorType Qp0 = this->GetPoint( iQp0 ).GetVectorFromOrigin( );
333 VectorType Qp1 = this->GetPoint( iQp1 ).GetVectorFromOrigin( );
334 VectorType Qm1 = this->GetPoint( iQm1 ).GetVectorFromOrigin( );
335 VectorType Qp2 = this->GetPoint( iQp2 ).GetVectorFromOrigin( );
336 VectorType Qm2 = this->GetPoint( iQm2 ).GetVectorFromOrigin( );
339 VectorType T( ValueType( 0 ) );
341 ValueType nT = T.GetNorm( );
342 if( nT > ValueType( 0 ) )
345 // Compute auxiliary vector
346 VectorType R( ValueType( 0 ) );
347 R = itk::CrossProduct( T, Qm1 - Qm2 );
348 R = itk::CrossProduct( R, Qp2 - Qp1 );
349 ValueType nR = R.GetNorm( );
350 if( nR > ValueType( 0 ) )
353 // TODO : psi??? see documentation
357 PointIdentifier iA = e->GetDestination( );
358 PointIdentifier iB = e->GetOnext( )->GetDestination( );
359 PointIdentifier iC = e->GetOnext( )->GetOnext( )->GetDestination( );
361 VectorType A = this->GetPoint( iA ).GetVectorFromOrigin( );
362 VectorType B = this->GetPoint( iB ).GetVectorFromOrigin( );
363 VectorType C = this->GetPoint( iC ).GetVectorFromOrigin( );
365 N = itk::CrossProduct( B - A, C - A );
366 ValueType nN = N.GetNorm( );
367 if( nN > ValueType( 0 ) )
374 #endif // __CPM__DATASTRUCTURES__SIMQLEXMESH__HXX__