MovementGenerator.cc

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
00003 //
00004 // This program is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU General Public License
00006 // as published by the Free Software Foundation; either version 2
00007 // of the License, or (at your option) any later version.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License
00015 // along with this program; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 //
00018 
00024 #include "MovementGenerator.h"
00025 
00026 std::ostream& operator<<(std::ostream& Stream, const NeighborMapEntry& e)
00027 {
00028     return Stream << "Positon: " << e.position << " Direction: " << e.direction;
00029 }
00030 
00031 MovementGenerator::MovementGenerator(double areaDimension, double speed, NeighborMap *Neighbors, GlobalCoordinator* coordinator, CollisionList* CollisionRect)
00032 {
00033     this->areaDimension = areaDimension;
00034     this->speed = speed;
00035     this->Neighbors = Neighbors;
00036     this->coordinator = coordinator;
00037     this->CollisionRect = CollisionRect;
00038 
00039     Vector2D center(areaDimension / 2, areaDimension / 2);
00040     position.x = uniform(0.0, areaDimension);
00041     position.y = uniform(0.0, areaDimension);
00042     direction = center - position;
00043     direction.normalize();
00044     if(CollisionRect != NULL) {
00045         generateScenery(coordinator->getSeed());
00046     }
00047 }
00048 
00049 Vector2D MovementGenerator::getPosition()
00050 {
00051     return position;
00052 }
00053 
00054 bool MovementGenerator::testBounds()
00055 {
00056     bool obstacleHit = false;
00057 
00058     if(position.x < 0.0) {
00059         position.x = 0.0;
00060     }
00061     if(position.x > areaDimension) {
00062        position.x = areaDimension;
00063     }
00064     if(position.y < 0.0) {
00065         position.y = 0.0;
00066     }
00067     if(position.y > areaDimension) {
00068         position.y = areaDimension;
00069     }
00070 
00071     double cosAngle = direction.x;
00072     SCDir scDirection;
00073     if(cosAngle > 0.71) {
00074         scDirection = DIR_RIGHT;
00075     }
00076     else if(cosAngle < -0.71) {
00077         scDirection = DIR_LEFT;
00078     }
00079     else if(direction.y > 0.0) {
00080         scDirection = DIR_UP;
00081     }
00082     else {
00083         scDirection = DIR_DOWN;
00084     }
00085 
00086     if(CollisionRect != NULL) {
00087         CollisionList::iterator i;
00088         for(i = CollisionRect->begin(); i != CollisionRect->end(); ++i) {
00089             if(i->collide(position)) {
00090                 switch(scDirection) {
00091                     case DIR_UP:
00092                         position.y = i->bottom();
00093                         direction.x = 1.0;
00094                         direction.y = 0.0;
00095                         break;
00096                     case DIR_DOWN:
00097                         position.y = i->top();
00098                         direction.x = -1.0;
00099                         direction.y = 0.0;
00100                         break;
00101                     case DIR_LEFT:
00102                         position.x = i->right();
00103                         direction.x = 0.0;
00104                         direction.y = 1.0;
00105                         break;
00106                     case DIR_RIGHT:
00107                         position.x = i->left();
00108                         direction.x = 0.0;
00109                         direction.y = -1.0;
00110                         break;
00111                 }
00112                 obstacleHit = true;
00113             }
00114         }
00115     }
00116 
00117     return obstacleHit;
00118 }
00119 
00120 void MovementGenerator::flock()
00121 {
00122     Vector2D separation, alignment, cohesion, toTarget;
00123     int NeighborCount = 0;
00124 
00125     for(itNeighbors = Neighbors->begin(); itNeighbors != Neighbors->end(); ++itNeighbors)
00126         if(position.distanceSqr(itNeighbors->second.position) < 2.5 && direction.cosAngle(itNeighbors->second.position - position) > -0.75) {
00127             separation += position - itNeighbors->second.position;
00128             alignment += itNeighbors->second.direction;
00129             cohesion += itNeighbors->second.position;
00130             ++NeighborCount;
00131         }
00132 
00133     if(NeighborCount > 0) {
00134         cohesion /= (double)NeighborCount;
00135         cohesion = cohesion - position;
00136         separation.normalize();
00137         alignment.normalize();
00138         cohesion.normalize();
00139     }
00140     toTarget = target - position;
00141     toTarget.normalize();
00142 
00143     direction = separation * 0.4 + alignment * 0.1 + cohesion * 0.35 + toTarget * 0.25;
00144     direction.normalize();
00145 }
00146 
00147 void MovementGenerator::generateScenery(unsigned int seed)
00148 {
00149     int dimension = (int)(areaDimension - 10.0);
00150     int sceneryType;
00151     double sceneryX, sceneryY;
00152 
00153     srand(seed);
00154 
00155     for(int i = 0; i < dimension; i += 10) {
00156         for(int j = 0; j < dimension; j+= 10) {
00157             sceneryType = rand() % 3;
00158             switch(sceneryType) {
00159                 case 0: { // mud
00160                     // do nothing except calling rand() for deterministic scenery generation
00161                     sceneryX = rand();
00162                     sceneryY = rand();
00163                 } break;
00164                 case 1: { // rock
00165                     sceneryX = 1 + (rand() % 8);
00166                     sceneryY = 1 + (rand() % 8);
00167                     CollisionRect->insert(CollisionRect->begin(), BoundingBox2D(i + sceneryX - 0.25, j + sceneryY - 0.5, i + sceneryX + 1.25, j + sceneryY + 0.25));
00168                 } break;
00169                 case 2: { // tree
00170                     sceneryX = 1 + (rand() % 6);
00171                     sceneryY = 1 + (rand() % 5);
00172                     CollisionRect->insert(CollisionRect->begin(), BoundingBox2D(i + sceneryX, j + sceneryY + 2.0, i + sceneryX + 3.0, j + sceneryY + 3.5));
00173                 } break;
00174             }
00175         }
00176     }
00177 }
Generated on Wed May 26 16:21:14 2010 for OverSim by  doxygen 1.6.3