LCOV - code coverage report
Current view: top level - src/utils/shapes - PolygonDynamics.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 76 76
Test Date: 2024-11-22 15:46:21 Functions: 100.0 % 6 6

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2004-2024 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    PolygonDynamics.cpp
      15              : /// @author  Leonhard Luecken
      16              : /// @date    Apr 2019
      17              : ///
      18              : // A polygon, which holds a timeSpan for displaying dynamic properties
      19              : /****************************************************************************/
      20              : 
      21              : 
      22              : #include "PolygonDynamics.h"
      23              : 
      24              : #include <assert.h>
      25              : #include "utils/common/StdDefs.h"
      26              : #include "utils/common/SUMOTime.h"
      27              : #include "utils/vehicle/SUMOTrafficObject.h"
      28              : 
      29              : 
      30              : //#define DEBUG_DYNAMIC_SHAPES
      31              : 
      32          156 : PolygonDynamics::PolygonDynamics(double creationTime,
      33              :                                  SUMOPolygon* p,
      34              :                                  SUMOTrafficObject* trackedObject,
      35              :                                  const std::vector<double>& timeSpan,
      36              :                                  const std::vector<double>& alphaSpan,
      37              :                                  bool looped,
      38          156 :                                  bool rotate) :
      39          156 :     myPolygon(p),
      40          156 :     myCurrentTime(0),
      41          156 :     myLastUpdateTime(creationTime),
      42          156 :     animated(!timeSpan.empty()),
      43          156 :     looped(looped),
      44          156 :     tracking(trackedObject != nullptr),
      45          156 :     rotate(rotate),
      46          156 :     myTrackedObject(trackedObject),
      47          156 :     myTrackedObjectID(""),
      48              :     myTrackedObjectsInitialPositon(nullptr),
      49          156 :     myTrackedObjectsInitialAngle(-1),
      50              :     myOriginalShape(nullptr),
      51              :     myTimeSpan(nullptr),
      52              :     myAlphaSpan(nullptr),
      53          156 :     myVis(nullptr) {
      54              :     // Check for consistency
      55          156 :     if (animated) {
      56          218 :         myTimeSpan = std::unique_ptr<std::vector<double> >(new std::vector<double>(timeSpan));
      57              :         assert(myTimeSpan->size() >= 2);
      58              :         assert((*myTimeSpan)[0] == 0.0);
      59              :         assert(myAlphaSpan == nullptr || myAlphaSpan->size() >= 2);
      60              : #ifdef DEBUG_DYNAMIC_SHAPES
      61              :         if (myTimeSpan->size() >= 2) {
      62              :             for (unsigned int i = 1; i < myTimeSpan->size(); ++i) {
      63              :                 assert((*myTimeSpan)[i - 1] <= (*myTimeSpan)[i]);
      64              :             }
      65              :         }
      66              : #endif
      67          109 :         myPrevTime = myTimeSpan->begin();
      68          109 :         myNextTime = ++myTimeSpan->begin();
      69              :     }
      70              : #ifdef DEBUG_DYNAMIC_SHAPES
      71              :     else  {
      72              :         assert(myAlphaSpan == nullptr);
      73              :     }
      74              : #endif
      75              : 
      76          156 :     myOriginalShape = std::unique_ptr<PositionVector>(new PositionVector(p->getShape()));
      77              : 
      78          156 :     if (tracking) {
      79              :         // Try initializing the tracked position (depends on whether object is already on the road)
      80          111 :         initTrackedPosition();
      81          111 :         myTrackedObjectID = myTrackedObject->getID();
      82              :     }
      83              : 
      84          156 :     if (!alphaSpan.empty()) {
      85          186 :         myAlphaSpan = std::unique_ptr<std::vector<double> >(new std::vector<double>(alphaSpan));
      86              :         assert(myAlphaSpan->size() >= 2);
      87              :         assert(myAlphaSpan->size() == myTimeSpan->size());
      88           93 :         myPrevAlpha = myAlphaSpan->begin();
      89           93 :         myNextAlpha = ++myAlphaSpan->begin();
      90              :     }
      91          156 : }
      92              : 
      93          312 : PolygonDynamics::~PolygonDynamics()
      94          468 : {}
      95              : 
      96              : 
      97              : SUMOTime
      98         3434 : PolygonDynamics::update(SUMOTime t) {
      99              : #ifdef DEBUG_DYNAMIC_SHAPES
     100              :     std::cout << t << " PolygonDynamics::update() for polygon '" << myPolygon->getID() << "'" << std::endl;
     101              : #endif
     102         3434 :     const double simtime = STEPS2TIME(t);
     103         3434 :     const double dt = simtime - myLastUpdateTime;
     104         3434 :     myLastUpdateTime = simtime;
     105              : 
     106         3434 :     SUMOTime ret = DELTA_T;
     107              : 
     108         3434 :     if (tracking) {
     109         3249 :         if (myTrackedObjectsInitialPositon == nullptr) {
     110              :             // Tracked object hasn't entered the network, until now.
     111              :             // Continuously try to obtain its initial position
     112            8 :             initTrackedPosition();
     113              :         }
     114         3249 :         if (myTrackedObjectsInitialPositon != nullptr) {
     115              :             // Initial position was initialized, relative tracking is possible
     116         3249 :             const Position& objPos = myTrackedObject->getPosition();
     117              :             const bool onRoad = objPos != Position::INVALID;
     118              :             if (onRoad) {
     119              : #ifdef DEBUG_DYNAMIC_SHAPES
     120              :                 std::cout << " Tracked object '" << myTrackedObject->getID() << "' is on the road. Tracked position=" << objPos << std::endl;
     121              : #endif
     122              :                 // Update polygon's shape
     123              :                 PositionVector newShape(*myOriginalShape);
     124         3249 :                 if (rotate) {
     125         3249 :                     const double relRotation = myTrackedObject->getAngle() - myTrackedObjectsInitialAngle;
     126         3249 :                     newShape.rotate2D(relRotation);
     127              : #ifdef DEBUG_DYNAMIC_SHAPES
     128              :                     std::cout << " Relative rotation wrt original rotation: " << relRotation << std::endl;
     129              : #endif
     130              :                 }
     131         3249 :                 newShape.add(objPos);
     132         3249 :                 myPolygon->setShape(newShape);
     133         3249 :             }
     134              : #ifdef DEBUG_DYNAMIC_SHAPES
     135              :             else {
     136              :                 // tracked object is off road
     137              :                 std::cout << " Tracked object '" << myTrackedObject->getID() << "' is off road." << std::endl;
     138              :             }
     139              : #endif
     140              :         }
     141              : #ifdef DEBUG_DYNAMIC_SHAPES
     142              :         else {
     143              :             // Initial position was not initialized, yet
     144              :             std::cout << " Tracked object '" << myTrackedObject->getID() << "' hasn't entered the network since tracking was started." << std::endl;
     145              :         }
     146              : #endif
     147              :     }
     148              : 
     149         3434 :     if (animated) {
     150              :         // Continue animation
     151          921 :         myCurrentTime += dt;
     152         2196 :         while (myCurrentTime >= *myNextTime) {
     153              :             // step forward along time lines to appropriate anchor points
     154              :             ++myPrevTime;
     155              :             ++myNextTime;
     156          455 :             if (myNextTime == myTimeSpan->end()) {
     157              :                 // Set iterators back to point to valid positions
     158              :                 --myPrevTime;
     159              :                 --myNextTime;
     160              :                 break;
     161              :             } else {
     162              :                 // Forward corresponding iterators for property time lines
     163          354 :                 if (myAlphaSpan != nullptr) {
     164              :                     ++myPrevAlpha;
     165              :                     ++myNextAlpha;
     166              :                 }
     167              :             }
     168              :         }
     169              : 
     170              :         // Linear interpolation factor between previous and next time
     171              :         double theta = 1.0;
     172              : #ifdef DEBUG_DYNAMIC_SHAPES
     173              :         std::cout << " animation: dt=" << dt
     174              :                   << ", current animation time: " << myCurrentTime
     175              :                   << ", previous anchor time: " << *myPrevTime
     176              :                   << ", next anchor time: " << *myNextTime;
     177              : #endif
     178          921 :         if (looped) {
     179           80 :             const bool resetAnimation = myCurrentTime >= *myNextTime;
     180              : #ifdef DEBUG_DYNAMIC_SHAPES
     181              :             if (resetAnimation) {
     182              :                 std::cout << " (resetting animation!)";
     183              :             }
     184              : #endif
     185           80 :             if (resetAnimation) {
     186              :                 // Reset animation time line to start, if appropriate
     187           32 :                 while (myCurrentTime >= *myNextTime) {
     188           16 :                     myCurrentTime -= *myNextTime;
     189              :                 }
     190           16 :                 myCurrentTime = MAX2(myCurrentTime, 0.0);
     191           16 :                 myPrevTime = myTimeSpan->begin();
     192           16 :                 myNextTime = ++myTimeSpan->begin();
     193           16 :                 if (myAlphaSpan != nullptr) {
     194           16 :                     myPrevAlpha = myAlphaSpan->begin();
     195           16 :                     myNextAlpha = ++myAlphaSpan->begin();
     196              :                 }
     197              :             }
     198              :         }
     199          921 :         if (myCurrentTime >= *myNextTime) {
     200              :             assert(!looped);
     201              :             // Reached the end of the dynamics, indicate expiration by returning zero
     202              :             // and set all properties to the final state (theta remains one)
     203              :             ret = 0;
     204              : #ifdef DEBUG_DYNAMIC_SHAPES
     205              :             std::cout << " (animation elapsed!)";
     206              : #endif
     207              :         } else {
     208              :             // Animation is still going on, schedule next update
     209          836 :             if (*myNextTime - *myPrevTime != 0) {
     210          836 :                 theta = (myCurrentTime - *myPrevTime) / (*myNextTime - *myPrevTime);
     211              :             }
     212              :         }
     213          921 :         if (myAlphaSpan != nullptr) {
     214              :             // Interpolate values of properties
     215          801 :             setAlpha(*myPrevAlpha + theta * (*myNextAlpha - *myPrevAlpha));
     216              : #ifdef DEBUG_DYNAMIC_SHAPES
     217              :             std::cout << ", previous anchor alpha: " << *myPrevAlpha
     218              :                       << ", next anchor alpha: " << *myNextAlpha;
     219              : #endif
     220              :         }
     221              : #ifdef DEBUG_DYNAMIC_SHAPES
     222              :         std::cout << ", theta=" << theta << std::endl;
     223              : #endif
     224              :     }
     225         3434 :     return ret;
     226              : }
     227              : 
     228              : void
     229          119 : PolygonDynamics::initTrackedPosition() {
     230          119 :     const Position& objPos = myTrackedObject->getPosition();
     231              :     if (objPos != Position::INVALID) {
     232              :         // Initialize Position of tracked object
     233          111 :         myTrackedObjectsInitialPositon = std::unique_ptr<Position>(new Position(objPos));
     234          111 :         myTrackedObjectsInitialAngle = myTrackedObject->getAngle();
     235              :         // Store original polygon shape relative to the tracked object's original position
     236          111 :         myOriginalShape->sub(*myTrackedObjectsInitialPositon);
     237              : #ifdef DEBUG_DYNAMIC_SHAPES
     238              :         std::cout << " Tracking object '" << myTrackedObject->getID() << "' at initial positon: " << *myTrackedObjectsInitialPositon << std::endl;
     239              : #endif
     240              :     }
     241          119 : }
     242              : 
     243              : void
     244          801 : PolygonDynamics::setAlpha(double alpha) {
     245          801 :     int a = (int) alpha;
     246          801 :     myPolygon->setShapeAlpha((unsigned char) a);
     247              : #ifdef DEBUG_DYNAMIC_SHAPES
     248              :     std::cout << "\n   DynamicPolygon::setAlpha() Converted alpha=" << alpha << " into myAlpha=" << a << std::endl;
     249              : #endif
     250          801 : }
        

Generated by: LCOV version 2.0-1