1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | cfMesh: A library for mesh generation
5 \\ / A nd | Author: Franjo Juretic (franjo.juretic@c-fields.com)
6 \\/ M anipulation | Copyright (C) Creative Fields, Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of cfMesh.
11 cfMesh is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 3 of the License, or (at your
14 option) any later version.
16 cfMesh is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with cfMesh. If not, see <http://www.gnu.org/licenses/>.
26 \*---------------------------------------------------------------------------*/
28 #include "meshOctree.H"
31 //#define OCTREE_DEBUG
33 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
38 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
39 // Private member functions
41 label meshOctree::findLeafContainingVertex
47 Info << "Finding leaf for vertex " << p << endl;
50 const meshOctreeCube* ocPtr = initialCubePtr_;
52 if( !ocPtr->isVertexInside(rootBox_, p) )
55 Info << "Vertex " << p << " is not in the initial cube" << endl;
60 "label meshOctree::findLeafContainingVertex(const point&) const"
61 ) << "Point " << p << " is not inside the initial cube" << endl;
63 throw "Found invalid locations of points";
72 if( ocPtr && !ocPtr->isLeaf() )
74 //- find a subCube containing the vertex;
75 const point c = ocPtr->centre(rootBox_);
83 if( !isQuadtree_ && p.z() >= c.z() )
86 ocPtr = ocPtr->subCube(scI);
96 return ocPtr->cubeLabel();
99 return meshOctreeCubeBasic::OTHERPROC;
102 void meshOctree::findLeavesInSphere
106 DynList<label>& containedLeaves
109 containedLeaves.clear();
111 initialCubePtr_->leavesInSphere(rootBox_, c, r, containedLeaves);
114 label meshOctree::findNeighbourOverNode
116 const meshOctreeCubeCoordinates& cc,
123 const meshOctreeCubeCoordinates nc(cc + regularityPositions_[18+nodeI]);
125 const meshOctreeCube* neiPtr = findCubeForPosition(nc);
129 const label levelLimiter = (1 << cc.level());
131 (nc.posX() >= levelLimiter) || (nc.posX() < 0) ||
132 (nc.posY() >= levelLimiter) || (nc.posY() < 0) ||
133 (!isQuadtree_ && (nc.posZ() >= levelLimiter || nc.posZ() < 0)) ||
134 (isQuadtree_ && (nc.posZ() != initialCubePtr_->posZ()))
139 else if( Pstream::parRun() )
141 return meshOctreeCubeBasic::OTHERPROC;
146 else if( neiPtr->isLeaf() )
149 if( leaves_[neiPtr->cubeLabel()] != neiPtr )
150 FatalError << "Cube does not correspond to itself"
151 << abort(FatalError);
153 return neiPtr->cubeLabel();
157 FixedList<label, 8> sc(-1);
158 for(label scI=0;scI<8;++scI)
160 meshOctreeCube* scPtr = neiPtr->subCube(scI);
163 sc[scI] = scPtr->cubeLabel();
165 else if( Pstream::parRun() )
167 sc[scI] = meshOctreeCubeBasic::OTHERPROC;
176 "label meshOctree::findNeighbourOverNode("
177 "const meshOctreeCubeCoordinates& cc,"
178 "const label nodeI) const"
179 ) << "Should not be here!" << abort(FatalError);
184 void meshOctree::findNeighboursOverEdge
186 const meshOctreeCubeCoordinates& cc,
188 DynList<label>& neighbourLeaves
191 if( isQuadtree_ && (eI < 8) )
193 neighbourLeaves.append(-1);
197 const meshOctreeCubeCoordinates nc(cc + regularityPositions_[6+eI]);
199 const meshOctreeCube* neiPtr = findCubeForPosition(nc);
203 const label levelLimiter = (1 << cc.level());
205 (nc.posX() >= levelLimiter) || (nc.posX() < 0) ||
206 (nc.posY() >= levelLimiter) || (nc.posY() < 0) ||
207 (!isQuadtree_ && (nc.posZ() >= levelLimiter || nc.posZ() < 0)) ||
208 (isQuadtree_ && (nc.posZ() != initialCubePtr_->posZ()))
211 neighbourLeaves.append(-1);
213 else if( Pstream::parRun() )
215 neighbourLeaves.append(meshOctreeCubeBasic::OTHERPROC);
218 else if( neiPtr->isLeaf() )
221 if( leaves_[neiPtr->cubeLabel()] != neiPtr )
222 FatalError << "Cube does not correspond to itself"
223 << abort(FatalError);
225 neighbourLeaves.append(neiPtr->cubeLabel());
229 FixedList<label, 8> sc(-1);
230 for(label scI=0;scI<8;++scI)
232 meshOctreeCube* scPtr = neiPtr->subCube(scI);
236 sc[scI] = scPtr->cubeLabel();
238 else if( Pstream::parRun() )
240 sc[scI] = meshOctreeCubeBasic::OTHERPROC;
244 const label* eNodes = meshOctreeCubeCoordinates::edgeNodes_[eI];
248 neighbourLeaves.append(sc[7-eNodes[1]]);
249 neighbourLeaves.append(sc[7-eNodes[0]]);
253 if( sc[7-eNodes[1]] >= 0 )
254 neighbourLeaves.append(sc[7-eNodes[1]]);
255 if( (sc[7-eNodes[0]] >= 0) && (sc[7-eNodes[0]] != sc[7-eNodes[1]]) )
256 neighbourLeaves.append(sc[7-eNodes[0]]);
261 void meshOctree::findNeighboursInDirection
263 const meshOctreeCubeCoordinates& cc,
265 DynList<label>& neighbourLeaves
268 if( isQuadtree_ && dir >= 4 )
270 neighbourLeaves.append(-1);
274 label cpx = cc.posX();
275 label cpy = cc.posY();
276 label cpz = cc.posZ();
311 const meshOctreeCube* neiPtr =
314 meshOctreeCubeCoordinates(cpx, cpy, cpz, cc.level())
319 const label levelLimiter = (1 << cc.level());
321 (cpx >= levelLimiter) || (cpx < 0) ||
322 (cpy >= levelLimiter) || (cpy < 0) ||
323 (!isQuadtree_ && (cpz >= levelLimiter || cpz < 0)) ||
324 (isQuadtree_ && (cpz != initialCubePtr_->posZ()))
327 neighbourLeaves.append(-1);
329 else if( Pstream::parRun() )
331 neighbourLeaves.append(meshOctreeCubeBasic::OTHERPROC);
334 else if( neiPtr->isLeaf() )
337 if( leaves_[neiPtr->cubeLabel()] != neiPtr )
338 FatalError << "Cube does not correspond to itself"
339 << abort(FatalError);
341 neighbourLeaves.append(neiPtr->cubeLabel());
345 FixedList<label, 8> sc(-1);
346 for(label scI=0;scI<8;++scI)
348 meshOctreeCube* scPtr = neiPtr->subCube(scI);
352 sc[scI] = scPtr->cubeLabel();
354 else if( Pstream::parRun() )
356 sc[scI] = meshOctreeCubeBasic::OTHERPROC;
360 const label* fNodes = meshOctreeCubeCoordinates::faceNodes_[dir];
361 for(label i=0;i<4;++i)
363 if( isQuadtree_ && sc[7-fNodes[i]] < 0 )
366 neighbourLeaves.append(sc[7-fNodes[i]]);
371 void meshOctree::findNeighboursForLeaf
373 const meshOctreeCubeCoordinates& cc,
374 DynList<label>& neighbourLeaves
377 neighbourLeaves.clear();
379 const label nCubeFaces = isQuadtree_?4:6;
380 for(label i=0;i<nCubeFaces;++i)
382 findNeighboursInDirection(cc, i, neighbourLeaves);
386 void meshOctree::findAllLeafNeighbours
388 const meshOctreeCubeCoordinates& cc,
389 DynList<label>& neighbourLeaves
392 neighbourLeaves.clear();
394 //- neighbours over nodes
397 for(label i=0;i<8;++i)
398 neighbourLeaves.append(findNeighbourOverNode(cc, i));
400 //- neighbours over edges
401 for(label i=0;i<12;++i)
402 findNeighboursOverEdge(cc, i, neighbourLeaves);
404 //- neighbours over faces
405 for(label i=0;i<6;++i)
406 findNeighboursInDirection(cc, i, neighbourLeaves);
410 //- neighbours of an quadtree leaf
411 //- neighbours over edges
412 for(label i=8;i<12;++i)
413 findNeighboursOverEdge(cc, i, neighbourLeaves);
415 //- neighbours over faces
416 for(label i=0;i<4;++i)
417 findNeighboursInDirection(cc, i, neighbourLeaves);
421 void meshOctree::findLeavesForCubeVertex
424 const direction vrtI,
425 FixedList<label, 8>& neighbours
428 const meshOctreeCube* oc = leaves_[leafI];
429 const meshOctreeCubeCoordinates cc = oc->refineForPosition(vrtI);
431 FixedList<meshOctreeCubeCoordinates, 8> positions;
433 for(label i=0;i<8;++i)
435 positions[i] = cc + vrtLeavesPos_[vrtI][i];
438 forAll(positions, posI)
440 neighbours[posI] = -1;
442 const label nei = findLeafLabelForPosition(positions[posI]);
444 if( (nei > -1) && leaves_[nei]->isLeaf() )
445 neighbours[posI] = nei;
449 Info << "Cube " << *oc << endl;
450 Info << "Vertex " << short(vrtI) << endl;
451 Info << "Neighbours " << endl;
452 forAll(neighbours, nI)
454 Info << *neighbours[nI] << endl;
458 meshOctreeCube* meshOctree::findCubeForPosition
460 const meshOctreeCubeCoordinates& cc
464 Info << "Finding position " << cc << endl;
467 const label cpx = cc.posX();
468 const label cpy = cc.posY();
469 const label cpz = cc.posZ();
470 const direction l = cc.level();
472 label levelLimiter = (1 << l);
474 (cpx >= levelLimiter) || (cpx < 0) ||
475 (cpy >= levelLimiter) || (cpy < 0) ||
476 (!isQuadtree_ && (cpz >= levelLimiter || cpz < 0)) ||
477 (isQuadtree_ && (cpz != initialCubePtr_->posZ()))
483 meshOctreeCube* neiPtr(initialCubePtr_);
485 for(label i=(l-1);i>=0;--i)
487 if( neiPtr && !neiPtr->isLeaf() )
489 levelLimiter = (1 << i);
493 if( cpx & levelLimiter )
495 if( cpy & levelLimiter )
497 if( !isQuadtree_ && (cpz & levelLimiter) )
500 neiPtr = neiPtr->subCube(scI);
509 Info << "Found position is " << *neiPtr << endl;
515 label meshOctree::findLeafLabelForPosition
517 const meshOctreeCubeCoordinates& cc
520 const meshOctreeCube* ocPtr = findCubeForPosition(cc);
522 if( ocPtr && ocPtr->isLeaf() )
524 return ocPtr->cubeLabel();
526 else if( !ocPtr && (neiProcs_.size() != 0) )
528 const label levelLimiter = (1 << cc.level());
530 (cc.posX() < levelLimiter) && (cc.posX() >= 0) &&
531 (cc.posY() < levelLimiter) && (cc.posY() >= 0) &&
532 ((!isQuadtree_ && (cc.posZ() < levelLimiter && cc.posZ() >= 0)) ||
533 (isQuadtree_ && (cc.posZ() == initialCubePtr_->posZ())))
536 return meshOctreeCubeBasic::OTHERPROC;
543 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
545 } // End namespace Foam
547 // ************************************************************************* //