GridMap.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2013, Fraunhofer FKIE
00003  *
00004  * Authors: Bastian Gaspers
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *
00009  * * Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * * Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * * Neither the name of the Fraunhofer FKIE nor the names of its
00015  *   contributors may be used to endorse or promote products derived from
00016  *   this software without specific prior written permission.
00017  *
00018  * This file is part of the StructureColoring ROS package.
00019  *
00020  * The StructureColoring ROS package is free software:
00021  * you can redistribute it and/or modify it under the terms of the
00022  * GNU Lesser General Public License as published by the Free
00023  * Software Foundation, either version 3 of the License, or
00024  * (at your option) any later version.
00025  *
00026  * The StructureColoring ROS package is distributed in the hope that it will be useful,
00027  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00028  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00029  * GNU Lesser General Public License for more details.
00030  *
00031  * You should have received a copy of the GNU Lesser General Public License
00032  * along with The StructureColoring ROS package.
00033  * If not, see <http://www.gnu.org/licenses/>.
00034  */
00035 
00036 #include <structureColoring/grids/GridMap.h>
00037 #include <structureColoring/histograms/OutOfRangeException.h>
00038 
00039 //#include <iostream>
00040 
00041 GridMap::GridMap(const GridMap& gridMap, float xMin, float xMax, float yMin, float yMax,
00042                 unsigned int xOff, unsigned int xAdd, unsigned int yOff, unsigned int yAdd,
00043                 float cellSize)
00044 :PositionedGrid2D<NodeGridCell>(gridMap.getPlane3D(), xMin, xMax, yMin, yMax, cellSize){
00045         if(gridMap.getXMin() < xMin || gridMap.getXMax() > xMax
00046                         || gridMap.getYMin() < yMin || gridMap.getYMax() > yMax){
00047 //              std::cout << "INPUT: xmin " << xMin << "  xmax " << xMax << "  ymin " << yMin << "  ymax "<< yMax << std::endl;
00048 //              std::cout << "GridMap dimensions: xmin " << getXMin() << "  xmax " << getXMax() << "  ymin " << getYMin() << "  ymax "<< getYMax() << std::endl;
00049                 throw OutOfRangeException("Min and Max (x and y) have to include gridMap");
00050         }
00051 //      std::cout << "New GridMap from constructor, cellsize (" << cellSize << "), width ("
00052 //                      << getWidth() << ") height ("<< getHeight() << ")"<< std::endl;
00053 //      std::cout << "INPUT: xmin " << xMin << "  xmax " << xMax << "  ymin " << yMin << "  ymax "<< yMax << std::endl;
00054 //      std::cout << "GridMap dimensions: xmin " << getXMin() << "  xmax " << getXMax() << "  ymin " << getYMin() << "  ymax "<< getYMax() << std::endl;
00055     float scale = round(gridMap.getCellSize() / cellSize);
00056         unsigned int regionSize = scale +0.5f; // round to nearest integer
00057 //      assert(regionSize >= 0);
00058         if (regionSize == 0)
00059         {
00060         // TODO why is regionSize 0
00061                 printf("scale: %f, oldCellSize: %f, newCellSize: %f", scale, gridMap.getCellSize(),cellSize);
00062                 regionSize = 1;
00063         }
00064         for (unsigned int i = 0; i < gridMap.getWidth(); i++) {
00065                 for (unsigned int j = 0; j < gridMap.getHeight(); j++) {
00066                         if (!gridMap.Grid2D<NodeGridCell>::operator()(i, j).populated())
00067                                 continue;
00068                         unsigned int newX = static_cast<unsigned int> ((float(xOff) + scale * float(i)) +0.5f);
00069                         unsigned int newY = static_cast<unsigned int> ((float(yOff) + scale * float(j)) +0.5f);
00070                         for (unsigned int k = 0; k < regionSize; ++k) {
00071                                 if (newX + k >= mWidth)
00072                                         continue;
00073                                 for (unsigned int l = 0; l < regionSize; ++l) {
00074                                         if (newY + l >= mHeight)
00075                                                 continue;
00076                                         this->Grid2D<NodeGridCell>::operator()(newX + k, newY + l).blindPopulate();
00077                                 }
00078                         }
00079                 }
00080         }
00081 
00082         mGridCCStartPos.first += xOff;
00083         mGridCCStartPos.second += yOff;
00084 }
00085 
00086 void GridMap::pushPopulatedUnvisitedNeighbors(std::queue<std::pair<unsigned int, unsigned int> >& neighbors, const unsigned int& width, const unsigned int& height) const{
00087         assert((width<mWidth)&&(height<mHeight));
00088         //4-neighbors (straight ones)
00089         if(width > 0){
00090                 std::pair<unsigned int, unsigned int> n = std::make_pair(width-1, height);
00091                 if((!mGrid[getIndex(n.first, n.second, mWidth)].visited()) && (mGrid[getIndex(n.first, n.second, mWidth)].populated())){
00092                         neighbors.push(n);
00093                 }
00094         }
00095         if(width < mWidth-1){
00096                 std::pair<unsigned int, unsigned int> n = std::make_pair(width+1, height);
00097                 if((!mGrid[getIndex(n.first, n.second, mWidth)].visited()) && (mGrid[getIndex(n.first, n.second, mWidth)].populated())){
00098                         neighbors.push(n);
00099                 }
00100         }
00101         if(height > 0){
00102                 std::pair<unsigned int, unsigned int> n = std::make_pair(width, height-1);
00103                 if((!mGrid[getIndex(n.first, n.second, mWidth)].visited()) && (mGrid[getIndex(n.first, n.second, mWidth)].populated())){
00104                         neighbors.push(n);
00105                 }
00106         }
00107         if(height < mHeight-1){
00108                 std::pair<unsigned int, unsigned int> n = std::make_pair(width, height+1);
00109                 if((!mGrid[getIndex(n.first, n.second, mWidth)].visited()) && (mGrid[getIndex(n.first, n.second, mWidth)].populated())){
00110                         neighbors.push(n);
00111                 }
00112         }
00113         //8-neighbors (diagonal ones)
00114         if(width > 0 && height > 0){
00115                 std::pair<unsigned int, unsigned int> n = std::make_pair(width-1, height-1);
00116                 if((!mGrid[getIndex(n.first, n.second, mWidth)].visited()) && (mGrid[getIndex(n.first, n.second, mWidth)].populated())){
00117                         neighbors.push(n);
00118                 }
00119         }
00120         if(width < mWidth-1 && height > 0){
00121                 std::pair<unsigned int, unsigned int> n = std::make_pair(width+1, height-1);
00122                 if((!mGrid[getIndex(n.first, n.second, mWidth)].visited()) && (mGrid[getIndex(n.first, n.second, mWidth)].populated())){
00123                         neighbors.push(n);
00124                 }
00125         }
00126         if(width > 0 && height < mHeight-1){
00127                 std::pair<unsigned int, unsigned int> n = std::make_pair(width-1, height+1);
00128                 if((!mGrid[getIndex(n.first, n.second, mWidth)].visited()) && (mGrid[getIndex(n.first, n.second, mWidth)].populated())){
00129                         neighbors.push(n);
00130                 }
00131         }
00132         if(width < mWidth-1 && height < mHeight-1){
00133                 std::pair<unsigned int, unsigned int> n = std::make_pair(width+1, height+1);
00134                 if((!mGrid[getIndex(n.first, n.second, mWidth)].visited()) && (mGrid[getIndex(n.first, n.second, mWidth)].populated())){
00135                         neighbors.push(n);
00136                 }
00137         }
00138 }
00139 
00140 /*****************************************************************************/
00141 
00142 void GridMap::print() const{
00143         std::cout << "printing grid, width = " << mWidth << " height = " << mHeight << std::endl;
00144         for(unsigned int h = 0; h < mHeight; h++){
00145                 std::cout << "|";
00146                 for(unsigned int w = 0; w < mWidth; w++){
00147                         if (mGrid[getIndex(w, h, mWidth)].populated()) std::cout << "x|";
00148                         else std::cout << "-|";
00149                 }
00150                 std::cout << std::endl;
00151         }
00152 }
00153 
00154 void GridMap::print(const std::pair<unsigned int, unsigned int>& coords) const{
00155         std::cout << "printing grid, width = " << mWidth << " height = " << mHeight << std::endl;
00156         for(unsigned int h = 0; h < mHeight; h++){
00157                 std::cout << "|";
00158                 for(unsigned int w = 0; w < mWidth; w++){
00159                         if (mGrid[getIndex(w, h, mWidth)].populated())
00160                                 if(w == coords.first && h == coords.second)
00161                                         std::cout << "O|";
00162                                 else std::cout << "x|";
00163                         else if(w == coords.first && h == coords.second)
00164                                 std::cout << "O|";
00165                         else std::cout << "-|";
00166                 }
00167                 std::cout << std::endl;
00168         }
00169         std::cout << coords.first << " " << coords.second << std::endl;
00170 }
00171 
00172 /*****************************************************************************/
00173 
00174 void GridMap::startConnectedComponentAt(ConnectedComponent& ccc, const Indices& startPos) {
00175         std::queue<Indices> neighborsQueue;
00176         assert((startPos.first < getWidth()) && (startPos.second < getHeight()));
00177         if ((!(*this)(startPos.first, startPos.second).visited()) && ((*this)(startPos.first, startPos.second).populated())) {
00178                 neighborsQueue.push(startPos);
00179         }
00180         while (!neighborsQueue.empty()) {
00181                 Indices xy = neighborsQueue.front();
00182                 neighborsQueue.pop();
00183                 if ((!((*this)(xy.first, xy.second).visited())) && ((*this)(xy.first, xy.second).populated())) {
00184                         //fill queue with neighboring cells
00185                         pushPopulatedUnvisitedNeighbors(neighborsQueue, xy.first, xy.second);
00186                         //put current cell to current connected component
00187                         (*this)(xy.first, xy.second).visit();
00188                         ccc.addCell(xy);
00189                         for (std::vector<unsigned int>::const_iterator pop_it = (*this)(xy.first, xy.second).getPopulation().begin(); pop_it
00190                                         != (*this)(xy.first, xy.second).getPopulation().end(); pop_it++) {
00191                                 ccc.addNumberOfPoints(1);
00192                         }
00193                 }
00194         }
00195 }
00196 
00197 /*****************************************************************************/
00198 
00199 void GridMap::checkNodesAgainstGridConnection(NodeIndices& outNodeIndices, const NodePointers& inNodeCandidates, float newCellSize,
00200                 unsigned int minNodesCount) const {
00201         float xMin = 0.f, yMin = 0.f, xMax = 0.f, yMax = 0.f;
00202         unsigned int xOff = 0, xAdd = 0, yOff = 0, yAdd = 0;
00203         float nodeXMin = std::numeric_limits<float>::max();
00204         float nodeXMax = -std::numeric_limits<float>::max();
00205         float nodeYMin = std::numeric_limits<float>::max();
00206         float nodeYMax = -std::numeric_limits<float>::max();
00207         outNodeIndices.reserve(inNodeCandidates.size());
00208         for(NodePointers::const_iterator nit = inNodeCandidates.begin(); nit != inNodeCandidates.end(); ++nit){
00209                 Vec3 tPos(this->getPlane3D().transformToXYPlane((*nit)->value_.meanPos));
00210                 if(tPos.x() < nodeXMin) nodeXMin = tPos.x();
00211                 if(tPos.x() > nodeXMax) nodeXMax = tPos.x();
00212                 if(tPos.y() < nodeYMin) nodeYMin = tPos.y();
00213                 if(tPos.y() > nodeYMax) nodeYMax = tPos.y();
00214         }
00215         this->getNewExtremes(xMin, xMax, yMin, yMax, xOff, xAdd, yOff, yAdd, nodeXMin, nodeXMax, nodeYMin, nodeYMax, newCellSize);
00216         GridMap testGrid(*this, xMin, xMax, yMin, yMax, xOff, xAdd, yOff, yAdd, newCellSize);
00217         testGrid.calculateStartPos();
00218         //register OcTreeNodes with grid
00219         testGrid.populate(inNodeCandidates);
00220         //visit start-gridcell and start bfs or dfs if it is populated and not yet visited
00221         //store connected component -> store for each node, which component it is in
00222         ConnectedComponent ccc;
00223         testGrid.startConnectedComponentAt(ccc, testGrid.getStartPos());
00224         if (ccc.getNumPoints() > minNodesCount) { // minimum number of Nodes in one connected Component
00225                 testGrid.gatherNodesInCC(outNodeIndices, ccc);
00226         }
00227 }
00228 
00229 /*****************************************************************************/
00230 
00231 void GridMap::gatherNodesInCC(NodePointers& outputNodes, const ConnectedComponent& conComp,     const NodePointers& octreeNodes) const {
00232         for (unsigned int l = 0; l < conComp.getCells().size(); l++) {
00233                 const uints& gridPopulation = (*this)(conComp.getCells()[l].first, conComp.getCells()[l].second).getPopulation();
00234                 for (unsigned int j = 0; j < gridPopulation.size(); ++j) {
00235                         const unsigned int& node_idx = gridPopulation[j];
00236                         assert(node_idx < octreeNodes.size());
00237                         outputNodes.push_back(octreeNodes[node_idx]);
00238                 }
00239         }
00240 }
00241 
00242 /*****************************************************************************/
00243 
00244 void GridMap::gatherNodesInCC(NodeIndices& outputIndices, const ConnectedComponent& conComp) const {
00245         for (unsigned int l = 0; l < conComp.getCells().size(); l++) {
00246                 const uints& gridPopulation = (*this)(conComp.getCells()[l].first, conComp.getCells()[l].second).getPopulation();
00247                 for (unsigned int j = 0; j < gridPopulation.size(); ++j) {
00248                         const unsigned int& node_idx = gridPopulation[j];
00249                         outputIndices.push_back(node_idx);
00250                 }
00251         }
00252 }
00253 
00254 /*****************************************************************************/
00255 
00256 void GridMap::getConnectedComponentsAndNotConnectedNodes(NodePointersVec& nodesInCC, const NodePointers& inputOctreeNodes, float cellSize,
00257                 unsigned int minPlaneNodes, unsigned int minCCNodes, NodePointers* notConnectedNodesOutput){
00258         //visit every gridcell and start bfs or dfs if it is populated and not yet visited
00259         //store connected components -> store for each node, which component it is in
00260         ConnectedComponent ccc;
00261         this->startConnectedComponentAt(ccc, getStartPos());
00262         if (ccc.getNumPoints() > minPlaneNodes) {
00263                 if (ccc.getNumPoints() > minCCNodes) { // minimum number of Nodes in one connected Component
00264                         NodePointers ccNodes;
00265                         this->gatherNodesInCC(ccNodes, ccc, inputOctreeNodes);
00266                         nodesInCC.push_back(ccNodes);
00267                 } else {
00268                         // push_back nodes that are not connected with anything. These should be "freed" for HT primitiv detection
00269                         if (notConnectedNodesOutput)
00270                                 this->gatherNodesInCC(*notConnectedNodesOutput, ccc, inputOctreeNodes);
00271                 }
00272         }
00273         ccc.reset();
00274         for (unsigned int i = 0; i < mWidth; i++) {
00275                 for (unsigned int j = 0; j < mHeight; j++) {
00276                         this->startConnectedComponentAt(ccc, std::make_pair(i, j));
00277                         if (ccc.getNumPoints() > std::min(minPlaneNodes, minCCNodes)) { // minimum number of Nodes in one connected Component
00278                                 NodePointers ccNodes;
00279                                 this->gatherNodesInCC(ccNodes, ccc, inputOctreeNodes);
00280                                 nodesInCC.push_back(ccNodes);
00281                         } else {
00282                                 // push_back nodes that are not connected with anything. These should be freed for HT primitiv detection
00283                                 if (notConnectedNodesOutput)
00284                                         this->gatherNodesInCC(*notConnectedNodesOutput, ccc, inputOctreeNodes);
00285                         }
00286                         ccc.reset();
00287                 }
00288         }
00289 
00290 }
00291 
00292 /*****************************************************************************/
00293 
00294 void GridMap::getNewExtremes(float& xMinOut, float& xMaxOut, float& yMinOut, float& yMaxOut,
00295                 unsigned int& xOff, unsigned int& xAdd, unsigned int& yOff, unsigned int& yAdd,
00296                 float xMinIn, float xMaxIn, float yMinIn, float yMaxIn, float stepSize) const {
00297         xOff = xAdd = yOff = yAdd = 0;
00298         if (mXMin > xMinIn){
00299                 xOff = std::ceil((mXMin - xMinIn) / stepSize);
00300                 xMinOut = mXMin - xOff * stepSize;
00301         } else {
00302                 xMinOut = mXMin;
00303         }
00304         if (mXMax < xMaxIn){
00305                 xAdd = std::ceil((xMaxIn - mXMax) / stepSize);
00306                 xMaxOut = mXMax + xAdd * stepSize;
00307         } else {
00308                 xMaxOut = mXMax;
00309         }
00310         if (mYMin > yMinIn){
00311                 yOff = std::ceil((mYMin - yMinIn) / stepSize);
00312                 yMinOut = mYMin - yOff * stepSize;
00313         } else {
00314                 yMinOut = mYMin;
00315         }
00316         if (mYMax < yMaxIn){
00317                 yAdd = std::ceil((yMaxIn - mYMax) / stepSize);
00318                 yMaxOut = mYMax + yAdd * stepSize;
00319         } else {
00320                 yMaxOut = mYMax;
00321         }
00322 //      for(xMinOut = mXMin; xMinIn < xMinOut; xMinOut -= stepSize) ++xOff;
00323 //      for(xMaxOut = mXMax; xMaxIn > xMaxOut; xMaxOut += stepSize) ++xAdd;
00324 //      for(yMinOut = mYMin; yMinIn < yMinOut; yMinOut -= stepSize) ++yOff;
00325 //      for(yMaxOut = mYMax; yMaxIn > yMaxOut; yMaxOut += stepSize) ++yAdd;
00326 }
00327 
00328 /*****************************************************************************/
00329 
00330 //this "solution" is hacky and should not be called very often
00331 void GridMap::calculateStartPos(){
00332         for(unsigned int w=0; w<mWidth; w++){
00333                 for(unsigned int h=0; h<mHeight; h++){
00334                         if((*this)(w, h).populated()){
00335                                 mGridCCStartPos = std::make_pair(w, h);
00336                                 return;
00337                         }
00338                 }
00339         }
00340     assert(false); // if we are here, the grid size is zero or the grid is empty
00341 }


structure_coloring_fkie
Author(s): Bastian Gaspers
autogenerated on Sun Jan 5 2014 11:38:09