SUMO - Simulation of Urban MObility

NGRandomNetBuilder.cpp

Go to the documentation of this file.
00001 /****************************************************************************/
00007 // Additional structures for building random nets
00008 /****************************************************************************/
00009 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00010 // Copyright (C) 2001-2011 DLR (http://www.dlr.de/) and contributors
00011 /****************************************************************************/
00012 //
00013 //   This program is free software; you can redistribute it and/or modify
00014 //   it under the terms of the GNU General Public License as published by
00015 //   the Free Software Foundation; either version 2 of the License, or
00016 //   (at your option) any later version.
00017 //
00018 /****************************************************************************/
00019 
00020 
00021 // ===========================================================================
00022 // included modules
00023 // ===========================================================================
00024 #ifdef _MSC_VER
00025 #include <windows_config.h>
00026 #else
00027 #include <config.h>
00028 #endif
00029 
00030 #include <iostream>
00031 #include <math.h>
00032 #include <stdlib.h>
00033 #include "NGRandomNetBuilder.h"
00034 #include <utils/geom/GeomHelper.h>
00035 #include <utils/common/RandHelper.h>
00036 
00037 #ifdef CHECK_MEMORY_LEAKS
00038 #include <foreign/nvwa/debug_new.h>
00039 #endif // CHECK_MEMORY_LEAKS
00040 
00041 
00042 // ===========================================================================
00043 // method definitions
00044 // ===========================================================================
00045 // ---------------------------------------------------------------------------
00046 // TNeighbourDistribution-definitions
00047 // ---------------------------------------------------------------------------
00048 void
00049 TNeighbourDistribution::add(int NumNeighbours, SUMOReal ratio) throw() {
00050     myNeighbours[NumNeighbours] = ratio;
00051 }
00052 
00053 
00054 int
00055 TNeighbourDistribution::num() throw() {
00056     SUMOReal sum=0, RandValue;
00057     std::map<int, SUMOReal>::iterator i;
00058     // total sum of ratios
00059     for (i=myNeighbours.begin(); i!=myNeighbours.end(); ++i) {
00060         sum += (*i).second;
00061     }
00062     // RandValue = [0,sum]
00063     RandValue = RandHelper::rand(sum);
00064     // find selected item
00065     i = myNeighbours.begin();
00066     sum = (*i).second;
00067     while ((i != myNeighbours.end()) && (sum < RandValue)) {
00068         i++;
00069         sum += (*i).second;
00070     }
00071     return (*i).first;
00072 }
00073 
00074 
00075 // ---------------------------------------------------------------------------
00076 // NGRandomNetBuilder-definitions
00077 // ---------------------------------------------------------------------------
00078 NGRandomNetBuilder::NGRandomNetBuilder(NGNet& net, SUMOReal minAngle, SUMOReal minDistance,
00079                                        SUMOReal maxDistance, SUMOReal connectivity,
00080                                        int numTries, const TNeighbourDistribution& neighborDist) throw()
00081     : myNet(net), myMinLinkAngle(minAngle), myMinDistance(minDistance),
00082       myMaxDistance(maxDistance), myConnectivity(connectivity), myNumTries(numTries),
00083       myNeighbourDistribution(neighborDist) {
00084 }
00085 
00086 
00087 void
00088 NGRandomNetBuilder::removeOuterNode(NGNode* node) throw() {
00089     for (NGNodeList::iterator ni=myOuterNodes.begin(); ni!=myOuterNodes.end(); ++ni) {
00090         if (*ni==node) {
00091             myOuterNodes.erase(ni);
00092             return;
00093         }
00094     }
00095 }
00096 
00097 
00098 bool
00099 NGRandomNetBuilder::checkAngles(NGNode* node) throw() {
00100     bool check = true;
00101 
00102     if (node->LinkList.size() >  1) {
00103         // loop over all links
00104         NGEdgeList::iterator li;
00105         NGNode* ni;
00106         for (li = node->LinkList.begin(); li != node->LinkList.end(); ++li) {
00107             // calc vector of currentnode
00108             if ((*li)->getStartNode() == node) {
00109                 ni = (*li)->getEndNode();
00110             } else {
00111                 ni = (*li)->getStartNode();
00112             }
00113             Position v1(
00114                 ni->getPosition().x() - node->getPosition().x(),
00115                 ni->getPosition().y() - node->getPosition().y());
00116             // loop over all links
00117             NGEdgeList::iterator lj;
00118             for (lj = node->LinkList.begin(); lj != node->LinkList.end(); ++lj) {
00119                 if (li != lj) {
00120                     if ((*lj)->getStartNode() == node) {
00121                         ni = (*lj)->getEndNode();
00122                     } else {
00123                         ni = (*lj)->getStartNode();
00124                     }
00125                     Position v2(
00126                         ni->getPosition().x() - node->getPosition().x(),
00127                         ni->getPosition().y() - node->getPosition().y());
00128                     SUMOReal angle = GeomHelper::Angle2D(v1.x(), v1.y(), v2.x(), v2.y());
00129                     if (fabs((SUMOReal) angle) < myMinLinkAngle) {
00130                         check = false;
00131                     }
00132                 }
00133             }
00134         }
00135     }
00136     return check;
00137 }
00138 
00139 
00140 bool
00141 NGRandomNetBuilder::canConnect(NGNode* baseNode, NGNode* newNode) throw() {
00142     bool connectable=true;
00143     Position n1(baseNode->getPosition());
00144     Position n2(newNode->getPosition());
00145 
00146     // check for range between Basenode and Newnode
00147     if (connectable) {
00148         SUMOReal dist = n1.distanceTo(n2);
00149         if ((dist < myMinDistance) || (dist > myMaxDistance)) {
00150             connectable = false;
00151         }
00152     }
00153 
00154     // check for angle restrictions
00155     if (connectable) {
00156         connectable = checkAngles(baseNode);
00157     }
00158     if (connectable) {
00159         connectable = checkAngles(newNode);
00160     }
00161 
00162     // check for intersections and range restrictions with outer links
00163     if (connectable) {
00164         NGEdgeList::iterator li;
00165         li = myOuterLinks.begin();
00166         while ((connectable == true) && (li != myOuterLinks.end())) {
00167             // check intersection only if links don't share a node
00168             Position p1((*li)->getStartNode()->getPosition());
00169             Position p2((*li)->getEndNode()->getPosition());
00170             if ((baseNode != (*li)->getStartNode()) && (baseNode!= (*li)->getEndNode())
00171                     && (newNode != (*li)->getStartNode()) && (newNode!= (*li)->getEndNode())) {
00172                 connectable = !GeomHelper::intersects(n1, n2, p1, p2);
00173 
00174             }
00175             // check NewNode-To-Links distance only, if NewNode isn't part of link
00176             if ((connectable) &&
00177                     (newNode != (*li)->getStartNode()) && (newNode != (*li)->getEndNode())) {
00178                 SUMOReal dist = GeomHelper::distancePointLine(n2, p1, p2);
00179                 if ((dist < myMinDistance) && (dist > -1)) {
00180                     connectable = false;
00181                 }
00182             }
00183             li++;
00184         }
00185     }
00186     return connectable;
00187 }
00188 
00189 
00190 void
00191 NGRandomNetBuilder::findPossibleOuterNodes(NGNode* node) throw() {
00192     myConNodes.clear();
00193     NGNodeList::iterator ni;
00194     for (ni = myOuterNodes.begin(); ni != myOuterNodes.end(); ++ni) {
00195         NGNode* on=*ni;
00196         if (!node->connected(on)) {
00197             if ((node->getMaxNeighbours() > node->LinkList.size()) &&
00198                     ((on)->getMaxNeighbours() > (on)->LinkList.size())) {
00199                 if (canConnect(node, on)) {
00200                     myConNodes.push_back(on);
00201                 }
00202             }
00203         }
00204     }
00205 }
00206 
00207 
00208 bool
00209 NGRandomNetBuilder::createNewNode(NGNode* baseNode) throw() {
00210     // calculate position of new node based on BaseNode
00211     SUMOReal dist = RandHelper::rand(myMinDistance, myMaxDistance);
00212     SUMOReal angle = RandHelper::rand((SUMOReal)(2*PI));
00213     SUMOReal x = baseNode->getPosition().x() + dist * cos(angle);
00214     SUMOReal y = baseNode->getPosition().y() + dist * sin(angle);
00215     NGNode* newNode = new NGNode(myNet.getNextFreeID());
00216     newNode->setX(x);
00217     newNode->setY(y);
00218     newNode->setMaxNeighbours((SUMOReal) myNeighbourDistribution.num());
00219     NGEdge* newLink = new NGEdge(myNet.getNextFreeID(), baseNode, newNode);
00220     if (canConnect(baseNode, newNode)) {
00221         // add node
00222         myNet.add(newNode);
00223         myOuterNodes.push_front(newNode);
00224         // add link
00225         myNet.add(newLink);
00226         myOuterLinks.push_back(newLink);
00227         // check basenode for being outer node
00228         if (baseNode->LinkList.size() >= baseNode->getMaxNeighbours()) {
00229             removeOuterNode(baseNode);
00230         }
00231         return true;
00232     } else {
00233         delete newNode;
00234         return false;
00235     }
00236 }
00237 
00238 
00239 void
00240 NGRandomNetBuilder::createNet(int numNodes) throw() {
00241     myNumNodes = numNodes;
00242 
00243     NGNode* outerNode = new NGNode(myNet.getNextFreeID());
00244     outerNode->setX(0);
00245     outerNode->setY(0);
00246     outerNode->setMaxNeighbours(4);
00247 
00248     myNet.add(outerNode);
00249     myOuterNodes.push_back(outerNode);
00250 
00251     bool created = true;
00252     while (((int) myNet.nodeNo() < numNodes) && (myOuterNodes.size() > 0)) {
00253         // brings last element to front
00254         if (!created) {
00255             myOuterNodes.push_front(myOuterNodes.back());
00256             myOuterNodes.pop_back();
00257         }
00258         outerNode = myOuterNodes.back();
00259         findPossibleOuterNodes(outerNode);
00260         created = false;
00261         if ((myConNodes.size() > 0) && (RandHelper::rand() < myConnectivity)) {
00262             // create link
00263             NGEdge* newLink = new NGEdge(myNet.getNextFreeID(), outerNode, myConNodes.back());
00264             if (canConnect(outerNode, myConNodes.back())) {
00265                 // add link
00266                 myNet.add(newLink);
00267                 myOuterLinks.push_back(newLink);
00268                 // check nodes for being outer node
00269                 if (outerNode->LinkList.size() >= outerNode->getMaxNeighbours()) {
00270                     removeOuterNode(outerNode);
00271                 }
00272                 if (myConNodes.back()->LinkList.size() >= myConNodes.back()->getMaxNeighbours()) {
00273                     removeOuterNode(myConNodes.back());
00274                 }
00275                 created = true;
00276             } else {
00277                 delete newLink;
00278             }
00279         } else {
00280             int count=0;
00281             do {
00282                 created = createNewNode(outerNode);
00283                 count++;
00284             } while ((count <= myNumTries) && !created);
00285             if (!created) {
00286                 outerNode->setMaxNeighbours((SUMOReal) outerNode->LinkList.size());
00287                 myOuterNodes.remove(outerNode);
00288             }
00289         }
00290     }
00291 }
00292 
00293 
00294 /****************************************************************************/
00295 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines