00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "SMESH_OctreeNode.hxx"
00031
00032 #include "SMDS_SetIterator.hxx"
00033 #include <gp_Pnt.hxx>
00034
00035 using namespace std;
00036
00037
00045
00046 SMESH_OctreeNode::SMESH_OctreeNode (const TIDSortedNodeSet & theNodes, const int maxLevel,
00047 const int maxNbNodes , const double minBoxSize )
00048 :SMESH_Octree( new SMESH_Octree::Limit( maxLevel,minBoxSize)),
00049 myMaxNbNodes(maxNbNodes),
00050 myNodes(theNodes)
00051 {
00052 compute();
00053 }
00054
00055
00059
00060
00061 SMESH_OctreeNode::SMESH_OctreeNode (int maxNbNodes):
00062 SMESH_Octree(), myMaxNbNodes(maxNbNodes)
00063 {
00064 }
00065
00066
00070
00071
00072 SMESH_Octree* SMESH_OctreeNode::allocateOctreeChild() const
00073 {
00074 return new SMESH_OctreeNode(myMaxNbNodes);
00075 }
00076
00077
00083
00084
00085 Bnd_B3d* SMESH_OctreeNode::buildRootBox()
00086 {
00087 Bnd_B3d* box = new Bnd_B3d;
00088 TIDSortedNodeSet::iterator it = myNodes.begin();
00089 for (; it != myNodes.end(); it++) {
00090 const SMDS_MeshNode* n1 = *it;
00091 gp_XYZ p1( n1->X(), n1->Y(), n1->Z() );
00092 box->Add(p1);
00093 }
00094 if ( myNodes.size() <= myMaxNbNodes )
00095 myIsLeaf = true;
00096
00097 return box;
00098 }
00099
00100
00107
00108
00109 const bool SMESH_OctreeNode::isInside (const gp_XYZ& p, const double precision)
00110 {
00111 if (precision <= 0.)
00112 return !(getBox().IsOut(p));
00113 Bnd_B3d BoxWithPrecision = getBox();
00114 BoxWithPrecision.Enlarge(precision);
00115 return ! BoxWithPrecision.IsOut(p);
00116 }
00117
00118
00123
00124 void SMESH_OctreeNode::buildChildrenData()
00125 {
00126 gp_XYZ min = getBox().CornerMin();
00127 gp_XYZ max = getBox().CornerMax();
00128 gp_XYZ mid = (min + max)/2.;
00129
00130 TIDSortedNodeSet::iterator it = myNodes.begin();
00131 while (it != myNodes.end())
00132 {
00133 const SMDS_MeshNode* n1 = *it;
00134 int ChildBoxNum = getChildIndex( n1->X(), n1->Y(), n1->Z(), mid );
00135 SMESH_OctreeNode* myChild = dynamic_cast<SMESH_OctreeNode*> (myChildren[ChildBoxNum]);
00136 myChild->myNodes.insert(myChild->myNodes.end(),n1);
00137 myNodes.erase( it );
00138 it = myNodes.begin();
00139 }
00140 for (int i = 0; i < 8; i++)
00141 {
00142 SMESH_OctreeNode* myChild = dynamic_cast<SMESH_OctreeNode*> (myChildren[i]);
00143 if ( myChild->myNodes.size() <= myMaxNbNodes )
00144 myChild->myIsLeaf = true;
00145 }
00146 }
00147
00148
00155
00156 void SMESH_OctreeNode::NodesAround (const SMDS_MeshNode * Node,
00157 list<const SMDS_MeshNode*>* Result,
00158 const double precision)
00159 {
00160 gp_XYZ p(Node->X(), Node->Y(), Node->Z());
00161 if (isInside(p, precision))
00162 {
00163 if (isLeaf())
00164 {
00165 Result->insert(Result->end(), myNodes.begin(), myNodes.end());
00166 }
00167 else
00168 {
00169 for (int i = 0; i < 8; i++)
00170 {
00171 SMESH_OctreeNode* myChild = dynamic_cast<SMESH_OctreeNode*> (myChildren[i]);
00172 myChild->NodesAround(Node, Result, precision);
00173 }
00174 }
00175 }
00176 }
00177
00178
00186
00187
00188 bool SMESH_OctreeNode::NodesAround(const gp_XYZ &node,
00189 map<double, const SMDS_MeshNode*>& dist2Nodes,
00190 double precision)
00191 {
00192 if ( !dist2Nodes.empty() )
00193 precision = min ( precision, sqrt( dist2Nodes.begin()->first ));
00194 else if ( precision == 0. )
00195 precision = maxSize() / 2;
00196
00197
00198 if (isInside(node, precision))
00199 {
00200 if (!isLeaf())
00201 {
00202
00203 gp_XYZ mid = (getBox().CornerMin() + getBox().CornerMax()) / 2.;
00204 int nodeChild = getChildIndex( node.X(), node.Y(), node.Z(), mid );
00205 if ( ((SMESH_OctreeNode*) myChildren[nodeChild])->NodesAround(node, dist2Nodes, precision))
00206 return true;
00207
00208 for (int i = 0; i < 8; i++)
00209 if ( i != nodeChild )
00210 if (((SMESH_OctreeNode*) myChildren[i])->NodesAround(node, dist2Nodes, precision))
00211 return true;
00212 }
00213 else if ( NbNodes() > 0 )
00214 {
00215 double minDist = precision * precision;
00216 gp_Pnt p1 ( node.X(), node.Y(), node.Z() );
00217 set<const SMDS_MeshNode*>::iterator nIt = myNodes.begin();
00218 for ( ; nIt != myNodes.end(); ++nIt )
00219 {
00220 gp_Pnt p2 ( (*nIt)->X(), (*nIt)->Y(), (*nIt)->Z() );
00221 double dist2 = p1.SquareDistance( p2 );
00222 if ( dist2 < minDist )
00223 dist2Nodes.insert( make_pair( minDist = dist2, *nIt ));
00224 }
00225
00226
00227
00228 return ( sqrt( minDist) <= precision * 1e-12 );
00229 }
00230 }
00231 return false;
00232 }
00233
00234
00245
00246 void SMESH_OctreeNode::FindCoincidentNodes (TIDSortedNodeSet& theSetOfNodes,
00247 list< list< const SMDS_MeshNode*> >* theGroupsOfNodes,
00248 const double theTolerance,
00249 const int maxLevel,
00250 const int maxNbNodes)
00251 {
00252 SMESH_OctreeNode theOctreeNode(theSetOfNodes, maxLevel, maxNbNodes, theTolerance);
00253 theOctreeNode.FindCoincidentNodes (&theSetOfNodes, theTolerance, theGroupsOfNodes);
00254 }
00255
00256
00265
00266 void SMESH_OctreeNode::FindCoincidentNodes ( TIDSortedNodeSet* theSetOfNodes,
00267 const double theTolerance,
00268 list< list< const SMDS_MeshNode*> >* theGroupsOfNodes)
00269 {
00270 TIDSortedNodeSet::iterator it1 = theSetOfNodes->begin();
00271 list<const SMDS_MeshNode*>::iterator it2;
00272
00273 while (it1 != theSetOfNodes->end())
00274 {
00275 const SMDS_MeshNode * n1 = *it1;
00276
00277 list<const SMDS_MeshNode*> ListOfCoincidentNodes;
00278
00279 list<const SMDS_MeshNode*> * groupPtr = 0;
00280
00281
00282
00283 FindCoincidentNodes(n1, theSetOfNodes, &ListOfCoincidentNodes, theTolerance);
00284
00285
00286 for (it2 = ListOfCoincidentNodes.begin(); it2 != ListOfCoincidentNodes.end(); it2++)
00287 {
00288 const SMDS_MeshNode* n2 = *it2;
00289 if ( !groupPtr )
00290 {
00291 theGroupsOfNodes->push_back( list<const SMDS_MeshNode*>() );
00292 groupPtr = & theGroupsOfNodes->back();
00293 groupPtr->push_back( n1 );
00294 }
00295 if (groupPtr->front() > n2)
00296 groupPtr->push_front( n2 );
00297 else
00298 groupPtr->push_back( n2 );
00299 }
00300 if (groupPtr != 0)
00301 groupPtr->sort();
00302
00303 theSetOfNodes->erase(it1);
00304 it1 = theSetOfNodes->begin();
00305 }
00306 }
00307
00308
00317
00318 void SMESH_OctreeNode::FindCoincidentNodes (const SMDS_MeshNode * Node,
00319 TIDSortedNodeSet* SetOfNodes,
00320 list<const SMDS_MeshNode*>* Result,
00321 const double precision)
00322 {
00323 gp_XYZ p(Node->X(), Node->Y(), Node->Z());
00324 bool isInsideBool = isInside(p, precision);
00325
00326 if (isInsideBool)
00327 {
00328
00329 if (isLeaf())
00330 {
00331 gp_Pnt p1 (Node->X(), Node->Y(), Node->Z());
00332
00333 TIDSortedNodeSet myNodesCopy = myNodes;
00334 TIDSortedNodeSet::iterator it = myNodesCopy.begin();
00335 double tol2 = precision * precision;
00336 bool squareBool;
00337
00338 while (it != myNodesCopy.end())
00339 {
00340 const SMDS_MeshNode* n2 = *it;
00341
00342
00343
00344 if (Node->GetID() != n2->GetID())
00345 {
00346 gp_Pnt p2 (n2->X(), n2->Y(), n2->Z());
00347
00348 squareBool = (p1.SquareDistance( p2 ) <= tol2);
00349
00350
00351 if (squareBool)
00352 {
00353 Result->insert(Result->begin(), n2);
00354 SetOfNodes->erase( n2 );
00355 myNodes.erase( n2 );
00356 }
00357 }
00358
00359
00360 it++;
00361 }
00362 if (Result->size() > 0)
00363 myNodes.erase(Node);
00364 }
00365 else
00366 {
00367
00368 for (int i = 0; i < 8; i++)
00369 {
00370 SMESH_OctreeNode* myChild = dynamic_cast<SMESH_OctreeNode*> (myChildren[i]);
00371 myChild->FindCoincidentNodes(Node, SetOfNodes, Result, precision);
00372 }
00373 }
00374 }
00375 }
00376
00377
00381
00382
00383 void SMESH_OctreeNode::UpdateByMoveNode( const SMDS_MeshNode* node, const gp_Pnt& toPnt )
00384 {
00385 if ( isLeaf() )
00386 {
00387 TIDSortedNodeSet::iterator pNode = myNodes.find( node );
00388 bool nodeInMe = ( pNode != myNodes.end() );
00389
00390 bool pointInMe = isInside( toPnt.Coord(), 1e-10 );
00391
00392 if ( pointInMe != nodeInMe )
00393 {
00394 if ( pointInMe )
00395 myNodes.insert( node );
00396 else
00397 myNodes.erase( node );
00398 }
00399 }
00400 else if ( myChildren )
00401 {
00402 gp_XYZ mid = (getBox().CornerMin() + getBox().CornerMax()) / 2.;
00403 int nodeChild = getChildIndex( node->X(), node->Y(), node->Z(), mid );
00404 int pointChild = getChildIndex( toPnt.X(), toPnt.Y(), toPnt.Z(), mid );
00405 if ( nodeChild != pointChild )
00406 {
00407 ((SMESH_OctreeNode*) myChildren[ nodeChild ])->UpdateByMoveNode( node, toPnt );
00408 ((SMESH_OctreeNode*) myChildren[ pointChild ])->UpdateByMoveNode( node, toPnt );
00409 }
00410 }
00411 }
00412
00413
00417
00418 SMESH_OctreeNodeIteratorPtr SMESH_OctreeNode::GetChildrenIterator()
00419 {
00420 return SMESH_OctreeNodeIteratorPtr
00421 ( new SMDS_SetIterator< SMESH_OctreeNode*, SMESH_Octree** >
00422 ( myChildren, (( isLeaf() || !myChildren ) ? myChildren : &myChildren[ 8 ] )));
00423 }
00424
00425
00429
00430 SMDS_NodeIteratorPtr SMESH_OctreeNode::GetNodeIterator()
00431 {
00432 return SMDS_NodeIteratorPtr
00433 ( new SMDS_SetIterator< SMDS_pNode, TIDSortedNodeSet::const_iterator >
00434 ( myNodes.begin(), myNodes.size() ? myNodes.end() : myNodes.begin()));
00435 }