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 2001-2010 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             Position2D 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                     Position2D v2(
00125                         ni->getPosition().x() - node->getPosition().x(),
00126                         ni->getPosition().y() - node->getPosition().y());
00127                     SUMOReal angle = GeomHelper::Angle2D(v1.x(), v1.y(), v2.x(), v2.y());
00128                     if (fabs((SUMOReal) angle) < myMinLinkAngle)
00129                         check = false;
00130                 }
00131             }
00132         }
00133     }
00134     return check;
00135 }
00136 
00137 
00138 bool
00139 NGRandomNetBuilder::canConnect(NGNode *baseNode, NGNode *newNode) throw() {
00140     bool connectable=true;
00141     Position2D n1(baseNode->getPosition());
00142     Position2D n2(newNode->getPosition());
00143 
00144     // check for range between Basenode and Newnode
00145     if (connectable) {
00146         SUMOReal dist = n1.distanceTo(n2);
00147         if ((dist < myMinDistance) || (dist > myMaxDistance)) {
00148             connectable = false;
00149         }
00150     }
00151 
00152     // check for angle restrictions
00153     if (connectable) connectable = checkAngles(baseNode);
00154     if (connectable) connectable = checkAngles(newNode);
00155 
00156     // check for intersections and range restrictions with outer links
00157     if (connectable) {
00158         NGEdgeList::iterator li;
00159         li = myOuterLinks.begin();
00160         while ((connectable == true) && (li != myOuterLinks.end())) {
00161             // check intersection only if links don't share a node
00162             Position2D p1((*li)->getStartNode()->getPosition());
00163             Position2D p2((*li)->getEndNode()->getPosition());
00164             if ((baseNode != (*li)->getStartNode()) && (baseNode!= (*li)->getEndNode())
00165                     && (newNode != (*li)->getStartNode()) && (newNode!= (*li)->getEndNode())) {
00166                 connectable = !GeomHelper::intersects(n1, n2, p1, p2);
00167 
00168             }
00169             // check NewNode-To-Links distance only, if NewNode isn't part of link
00170             if ((connectable) &&
00171                     (newNode != (*li)->getStartNode()) && (newNode != (*li)->getEndNode())) {
00172                 SUMOReal dist = GeomHelper::distancePointLine(n2, p1, p2);
00173                 if ((dist < myMinDistance) && (dist > -1))
00174                     connectable = false;
00175             }
00176             li++;
00177         }
00178     }
00179     return connectable;
00180 }
00181 
00182 
00183 void
00184 NGRandomNetBuilder::findPossibleOuterNodes(NGNode *node) throw() {
00185     myConNodes.clear();
00186     NGNodeList::iterator ni;
00187     for (ni = myOuterNodes.begin(); ni != myOuterNodes.end(); ++ni) {
00188         NGNode *on=*ni;
00189         if (!node->connected(on)) {
00190             if ((node->getMaxNeighbours() > node->LinkList.size()) &&
00191                     ((on)->getMaxNeighbours() > (on)->LinkList.size())) {
00192                 if (canConnect(node, on)) {
00193                     myConNodes.push_back(on);
00194                 }
00195             }
00196         }
00197     }
00198 }
00199 
00200 
00201 bool
00202 NGRandomNetBuilder::createNewNode(NGNode *baseNode) throw() {
00203     // calculate position of new node based on BaseNode
00204     SUMOReal dist = RandHelper::rand(myMinDistance, myMaxDistance);
00205     SUMOReal angle = RandHelper::rand((SUMOReal)(2*PI));
00206     SUMOReal x = baseNode->getPosition().x() + dist * cos(angle);
00207     SUMOReal y = baseNode->getPosition().y() + dist * sin(angle);
00208     NGNode *newNode = new NGNode(myNet.getNextFreeID());
00209     newNode->setX(x);
00210     newNode->setY(y);
00211     newNode->setMaxNeighbours((SUMOReal) myNeighbourDistribution.num());
00212     NGEdge *newLink = new NGEdge(myNet.getNextFreeID(), baseNode, newNode);
00213     if (canConnect(baseNode, newNode)) {
00214         // add node
00215         myNet.add(newNode);
00216         myOuterNodes.push_front(newNode);
00217         // add link
00218         myNet.add(newLink);
00219         myOuterLinks.push_back(newLink);
00220         // check basenode for being outer node
00221         if (baseNode->LinkList.size() >= baseNode->getMaxNeighbours()) {
00222             removeOuterNode(baseNode);
00223         }
00224         return true;
00225     } else {
00226         delete newNode;
00227         return false;
00228     }
00229 }
00230 
00231 
00232 void
00233 NGRandomNetBuilder::createNet(int numNodes) throw() {
00234     myNumNodes = numNodes;
00235 
00236     NGNode *outerNode = new NGNode(myNet.getNextFreeID());
00237     outerNode->setX(0);
00238     outerNode->setY(0);
00239     outerNode->setMaxNeighbours(4);
00240 
00241     myNet.add(outerNode);
00242     myOuterNodes.push_back(outerNode);
00243 
00244     bool created = true;
00245     while (((int) myNet.nodeNo() < numNodes) && (myOuterNodes.size() > 0)) {
00246         // brings last element to front
00247         if (!created) {
00248             myOuterNodes.push_front(myOuterNodes.back());
00249             myOuterNodes.pop_back();
00250         }
00251         outerNode = myOuterNodes.back();
00252         findPossibleOuterNodes(outerNode);
00253         created = false;
00254         if ((myConNodes.size() > 0) && (RandHelper::rand() < myConnectivity)) {
00255             // create link
00256             NGEdge *newLink = new NGEdge(myNet.getNextFreeID(), outerNode, myConNodes.back());
00257             if (canConnect(outerNode, myConNodes.back())) {
00258                 // add link
00259                 myNet.add(newLink);
00260                 myOuterLinks.push_back(newLink);
00261                 // check nodes for being outer node
00262                 if (outerNode->LinkList.size() >= outerNode->getMaxNeighbours()) {
00263                     removeOuterNode(outerNode);
00264                 }
00265                 if (myConNodes.back()->LinkList.size() >= myConNodes.back()->getMaxNeighbours()) {
00266                     removeOuterNode(myConNodes.back());
00267                 }
00268                 created = true;
00269             } else {
00270                 delete newLink;
00271             }
00272         } else {
00273             int count=0;
00274             do {
00275                 created = createNewNode(outerNode);
00276                 count++;
00277             } while ((count <= myNumTries) && !created);
00278             if (!created) {
00279                 outerNode->setMaxNeighbours((SUMOReal) outerNode->LinkList.size());
00280                 myOuterNodes.remove(outerNode);
00281             }
00282         }
00283     }
00284 }
00285 
00286 
00287 /****************************************************************************/
00288 

Generated on Wed May 5 00:06:33 2010 for Sumo - Simulation of Urban MObility by  doxygen 1.5.6