/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see . Description \*---------------------------------------------------------------------------*/ #include "router.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // Foam::label Foam::router::count(const label weight) const { label cnt = 0; forAll(weights_, nodeI) { cnt += weights_[nodeI]; } return cnt; } // Given connections between nodes set minimum distance from nodeI void Foam::router::setWeights ( const label weight, const label nodeI ) { // Set weight at current node weights_[nodeI] = weight; const labelList& myNeighbours = connections_[nodeI]; forAll(myNeighbours, neighbourI) { if (weights_[myNeighbours[neighbourI]] > weight + 1) { // Distribute weight+1 to neighbours setWeights ( weight+1, myNeighbours[neighbourI] ); } } } // Mark shortest path from endNode to startNode by setting the weights // to 0. void Foam::router::fixWeights ( const label startNodeI, const label endNodeI, const label nodeI, const label prevNodeI ) { // Mark this node weights_[nodeI] = 0; label minNodeI = -1; label minDist = labelMax; label nMinNodes = 0; const labelList& myNeighbours = connections_[nodeI]; forAll(myNeighbours, neighbourI) { label nbrNodeI = myNeighbours[neighbourI]; if (nbrNodeI != prevNodeI) { if (weights_[nbrNodeI] == 0) { // Reached end minDist = 0; break; } else if (weights_[nbrNodeI] > 0) { if (weights_[nbrNodeI] < minDist) { minDist = weights_[nbrNodeI]; minNodeI = nbrNodeI; nMinNodes = 1; } else if (weights_[nbrNodeI] == minDist) { nMinNodes++; } } } } if (minDist == 0) { // Reached starting point. return; } if (minNodeI == -1) { WarningInFunction << "Cannot route from node " << nodeI << " since all neighbours of node " << "already allocated:" << endl; forAll(myNeighbours, neighbourI) { label nbrNodeI = myNeighbours[neighbourI]; WarningInFunction << " weight:" << weights_[nbrNodeI] << endl; } return; } if (nMinNodes > 1) { // Multiple paths, all with same weight. Use some heuristic // to choose one. Here: smallest angle to vector end-start vector n(coords_[endNodeI] - coords_[startNodeI]); scalar maxCosAngle = -GREAT; forAll(myNeighbours, neighbourI) { label nbrNodeI = myNeighbours[neighbourI]; if (weights_[nbrNodeI] == minDist) { vector n2(coords_[nbrNodeI] - coords_[startNodeI]); scalar magN2 = mag(n2); if (magN2 > SMALL) { n2 /= mag(n2); scalar cosAngle = n & n2; if (cosAngle > maxCosAngle) { maxCosAngle = cosAngle; minNodeI = nbrNodeI; } } } } } // Recursively go mark the path at minNode fixWeights ( startNodeI, endNodeI, minNodeI, nodeI ); } Foam::label Foam::router::getValue(const label pathValue) const { forAll(weights_, nodeI) { if (weights_[nodeI] == pathValue) { return nodeI; } } return -1; } // Find node which has no neighbours with pathValue Foam::label Foam::router::findEndNode ( const label startNodeI, const label prevNodeI, const label pathValue ) const { const labelList& myNeighbours = connections_[startNodeI]; forAll(myNeighbours, neighbourI) { label nodeI = myNeighbours[neighbourI]; if (nodeI != prevNodeI) { if (weights_[nodeI] == pathValue) { return findEndNode(nodeI, startNodeI, pathValue); } } } // No neighbours with pathValue found. Return this node return startNodeI; } // Append all pathValue weights to route. void Foam::router::storeRoute ( const label startNodeI, const label prevNodeI, const label pathValue, DynamicList