LCOV - code coverage report
Current view: top level - src/netgen - NGRandomNetBuilder.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 97 97
Test Date: 2025-11-13 15:38:19 Functions: 100.0 % 7 7

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    NGRandomNetBuilder.cpp
      15              : /// @author  Markus Hartinger
      16              : /// @author  Daniel Krajzewicz
      17              : /// @author  Michael Behrisch
      18              : /// @date    Mar, 2003
      19              : ///
      20              : // Additional structures for building random nets
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #include <iostream>
      25              : #include <cmath>
      26              : #include <stdlib.h>
      27              : #include "NGRandomNetBuilder.h"
      28              : #include <utils/geom/GeomHelper.h>
      29              : #include <utils/common/StdDefs.h>
      30              : #include <utils/common/RandHelper.h>
      31              : 
      32              : 
      33              : // ===========================================================================
      34              : // method definitions
      35              : // ===========================================================================
      36              : // ---------------------------------------------------------------------------
      37              : // NGRandomNetBuilder-definitions
      38              : // ---------------------------------------------------------------------------
      39           24 : NGRandomNetBuilder::NGRandomNetBuilder(NGNet& net, double minAngle, double minDistance,
      40              :                                        double maxDistance, double connectivity,
      41           24 :                                        int numTries, const RandomDistributor<int>& neighborDist)
      42           24 :     : myNet(net), myMinLinkAngle(minAngle), myMinDistance(minDistance),
      43           24 :       myMaxDistance(maxDistance), myConnectivity(connectivity), myNumTries(numTries),
      44           24 :       myNeighbourDistribution(neighborDist) {
      45           24 : }
      46              : 
      47              : 
      48              : void
      49         1657 : NGRandomNetBuilder::removeOuterNode(NGNode* node) {
      50        60984 :     for (NGNodeList::iterator ni = myOuterNodes.begin(); ni != myOuterNodes.end(); ++ni) {
      51        60984 :         if (*ni == node) {
      52         1657 :             myOuterNodes.erase(ni);
      53              :             return;
      54              :         }
      55              :     }
      56              : }
      57              : 
      58              : 
      59              : bool
      60        91617 : NGRandomNetBuilder::checkAngles(const NGNode* const node) {
      61              :     bool check = true;
      62              : 
      63        91617 :     if (node->getLinks().size() >  1) {
      64              :         // loop over all links
      65              :         NGNode* ni;
      66       262944 :         for (NGEdge* const li : node->getLinks()) {
      67              :             // calc vector of currentnode
      68       198288 :             if (li->getStartNode() == node) {
      69              :                 ni = li->getEndNode();
      70              :             } else {
      71              :                 ni = li->getStartNode();
      72              :             }
      73              :             Position v1(
      74              :                 ni->getPosition().x() - node->getPosition().x(),
      75       198288 :                 ni->getPosition().y() - node->getPosition().y());
      76              :             // loop over all links
      77       876170 :             for (NGEdge* const lj : node->getLinks()) {
      78       677882 :                 if (li != lj) {
      79       479594 :                     if (lj->getStartNode() == node) {
      80              :                         ni = lj->getEndNode();
      81              :                     } else {
      82              :                         ni = lj->getStartNode();
      83              :                     }
      84              :                     Position v2(
      85              :                         ni->getPosition().x() - node->getPosition().x(),
      86       479594 :                         ni->getPosition().y() - node->getPosition().y());
      87       479594 :                     if (fabs(GeomHelper::angle2D(v1, v2)) < myMinLinkAngle) {
      88              :                         check = false;
      89              :                     }
      90              :                 }
      91              :             }
      92              :         }
      93              :     }
      94        91617 :     return check;
      95              : }
      96              : 
      97              : 
      98              : bool
      99       453348 : NGRandomNetBuilder::canConnect(NGNode* baseNode, NGNode* newNode) {
     100              :     bool connectable = true;
     101       453348 :     const PositionVector n(baseNode->getPosition(), newNode->getPosition());
     102              : 
     103              :     // check for range between Basenode and Newnode
     104              :     if (connectable) {
     105       453348 :         double dist = n.length();
     106       453348 :         if ((dist < myMinDistance) || (dist > myMaxDistance)) {
     107              :             connectable = false;
     108              :         }
     109              :     }
     110              : 
     111              :     // check for angle restrictions
     112              :     if (connectable) {
     113        57913 :         connectable = checkAngles(baseNode);
     114              :     }
     115        57913 :     if (connectable) {
     116        33704 :         connectable = checkAngles(newNode);
     117              :     }
     118              : 
     119              :     // check for intersections and range restrictions with outer links
     120        33704 :     if (connectable) {
     121              :         NGEdgeList::iterator li;
     122              :         li = myOuterLinks.begin();
     123      3316104 :         while (connectable && (li != myOuterLinks.end())) {
     124              :             // check intersection only if links don't share a node
     125      3285358 :             const NGNode* const start = (*li)->getStartNode();
     126              :             const NGNode* const end = (*li)->getEndNode();
     127              :             const Position& p1 = start->getPosition();
     128              :             const Position& p2 = end->getPosition();
     129      3285358 :             if ((baseNode != start) && (baseNode != end) && (newNode != start) && (newNode != end)) {
     130      3217328 :                 connectable = !n.intersects(p1, p2);
     131              :             }
     132              :             // check NewNode-To-Links distance only, if NewNode isn't part of link
     133      3285358 :             if (connectable && (newNode != start) && (newNode != end)) {
     134      3250938 :                 const double offset = GeomHelper::nearest_offset_on_line_to_point2D(p1, p2, n[1]);
     135      3250938 :                 if (offset != GeomHelper::INVALID_OFFSET) {
     136       265467 :                     const Position p = PositionVector(p1, p2).positionAtOffset2D(offset);
     137       265467 :                     const double dist = p.distanceTo2D(n[1]);
     138       265467 :                     if (dist < myMinDistance) {
     139              :                         connectable = false;
     140              :                     }
     141              :                 }
     142              :             }
     143              :             ++li;
     144              :         }
     145              :     }
     146       453348 :     return connectable;
     147       453348 : }
     148              : 
     149              : 
     150              : void
     151        11740 : NGRandomNetBuilder::findPossibleOuterNodes(NGNode* node) {
     152              :     myConNodes.clear();
     153              :     NGNodeList::iterator ni;
     154       430412 :     for (ni = myOuterNodes.begin(); ni != myOuterNodes.end(); ++ni) {
     155       418672 :         NGNode* on = *ni;
     156       418672 :         if (!node->connected(on)) {
     157       412499 :             if ((node->getMaxNeighbours() > (int)node->getLinks().size()) &&
     158       412499 :                     (on->getMaxNeighbours() > (int)on->getLinks().size())) {
     159       412499 :                 if (canConnect(node, on)) {
     160        13794 :                     myConNodes.push_back(on);
     161              :                 }
     162              :             }
     163              :         }
     164              :     }
     165        11740 : }
     166              : 
     167              : 
     168              : bool
     169        32482 : NGRandomNetBuilder::createNewNode(NGNode* baseNode, bool gridMode) {
     170              :     // calculate position of new node based on BaseNode
     171        32482 :     double dist = RandHelper::rand(myMinDistance, myMaxDistance);
     172              :     double angle = RandHelper::rand((double)(2 * M_PI));
     173        32482 :     if (gridMode) {
     174              :         // dist must be a multiple of minDist
     175         7341 :         dist = MAX2(1, int(dist / myMinDistance)) * myMinDistance;
     176              :         // angle must be a multiple of 90 degrees
     177         7341 :         angle = RandHelper::rand(4) * 0.5 * M_PI;
     178              :     }
     179        32482 :     double x = baseNode->getPosition().x() + dist * cos(angle);
     180        32482 :     double y = baseNode->getPosition().y() + dist * sin(angle);
     181        32482 :     NGNode* newNode = new NGNode(myNet.getNextFreeID());
     182              :     newNode->setX(x);
     183              :     newNode->setY(y);
     184        32482 :     newNode->setMaxNeighbours(myNeighbourDistribution.get());
     185        32482 :     NGEdge* newLink = new NGEdge(myNet.getNextFreeID(), baseNode, newNode);
     186        32482 :     if (canConnect(baseNode, newNode)) {
     187              :         // add node
     188         2998 :         myNet.add(newNode);
     189         2998 :         myOuterNodes.push_front(newNode);
     190              :         // add link
     191         2998 :         myNet.add(newLink);
     192         2998 :         myOuterLinks.push_back(newLink);
     193              :         // check basenode for being outer node
     194         2998 :         if ((int)baseNode->getLinks().size() >= baseNode->getMaxNeighbours()) {
     195         1238 :             removeOuterNode(baseNode);
     196              :         }
     197         2998 :         return true;
     198              :     } else {
     199        29484 :         delete newLink;
     200        29484 :         delete newNode;
     201        29484 :         return false;
     202              :     }
     203              : }
     204              : 
     205              : 
     206              : void
     207           24 : NGRandomNetBuilder::createNet(int numNodes, bool gridMode) {
     208           24 :     myNumNodes = numNodes;
     209              : 
     210           24 :     NGNode* outerNode = new NGNode(myNet.getNextFreeID());
     211              :     outerNode->setX(0);
     212              :     outerNode->setY(0);
     213              :     outerNode->setMaxNeighbours(4);
     214              : 
     215           24 :     myNet.add(outerNode);
     216           24 :     myOuterNodes.push_back(outerNode);
     217              : 
     218              :     bool created = true;
     219        11764 :     while ((myNet.nodeNo() < numNodes) && (myOuterNodes.size() > 0)) {
     220              :         // brings last element to front
     221        11740 :         if (!created) {
     222              :             myOuterNodes.push_front(myOuterNodes.back());
     223              :             myOuterNodes.pop_back();
     224              :         }
     225        11740 :         outerNode = myOuterNodes.back();
     226        11740 :         findPossibleOuterNodes(outerNode);
     227              :         created = false;
     228        11740 :         if ((myConNodes.size() > 0) && (RandHelper::rand() < myConnectivity)) {
     229              :             // create link
     230         8367 :             NGEdge* newLink = new NGEdge(myNet.getNextFreeID(), outerNode, myConNodes.back());
     231         8367 :             if (canConnect(outerNode, myConNodes.back())) {
     232              :                 // add link
     233         1180 :                 myNet.add(newLink);
     234         1180 :                 myOuterLinks.push_back(newLink);
     235              :                 // check nodes for being outer node
     236         1180 :                 if ((int)outerNode->getLinks().size() >= outerNode->getMaxNeighbours()) {
     237          256 :                     removeOuterNode(outerNode);
     238              :                 }
     239         1180 :                 if ((int)myConNodes.back()->getLinks().size() >= myConNodes.back()->getMaxNeighbours()) {
     240          163 :                     removeOuterNode(myConNodes.back());
     241              :                 }
     242              :                 created = true;
     243              :             } else {
     244         7187 :                 delete newLink;
     245              :             }
     246              :         } else {
     247              :             int count = 0;
     248              :             do {
     249        32482 :                 created = createNewNode(outerNode, gridMode);
     250        32482 :                 count++;
     251        32482 :             } while ((count <= myNumTries) && !created);
     252         3373 :             if (!created) {
     253          375 :                 outerNode->setMaxNeighbours((int)outerNode->getLinks().size());
     254          375 :                 myOuterNodes.remove(outerNode);
     255              :             }
     256              :         }
     257              :     }
     258           24 : }
     259              : 
     260              : 
     261              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1