Skip to content
Snippets Groups Projects
Select Git revision
  • 9ec5d18db36105ac380fc08b507fed2ed91a7f5f
  • 2023 default protected
2 results

mpi4py-3.0.3-iimpi-2020-Python-3.8.5.eb

Blame
  • Obstacle.cpp 9.48 KiB
    /**
     * \file        Obstacle.cpp
     * \date        Jul 31, 2012
     * \version     v0.7
     * \copyright   <2009-2015> Forschungszentrum Jülich GmbH. All rights reserved.
     *
     * \section License
     * This file is part of JuPedSim.
     *
     * JuPedSim is free software: you can redistribute it and/or modify
     * it under the terms of the GNU Lesser General Public License as published by
     * the Free Software Foundation, either version 3 of the License, or
     * any later version.
     *
     * JuPedSim is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU Lesser General Public License
     * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>.
     *
     * \section Description
     *
     *
     **/
    
    
    #include "Obstacle.h"
    
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <iterator>
    #include <string>
    #include <vector>
    
    #include "../IO/OutputHandler.h"
    #include "Line.h"
    #include "Point.h"
    #include "Wall.h"
    
    
    using namespace std;
    
    
    Obstacle::Obstacle()
    {
         _height=0.0;
         _id=-1;
         _caption="obstacle";
         _walls = vector<Wall > ();
         _poly = vector<Point > ();
    }
    
    Obstacle::~Obstacle() {}
    
    
    void Obstacle::AddWall(const Wall& w)
    {
         _walls.push_back(w);
    }
    
    string Obstacle::GetCaption() const
    {
         return _caption;
    }
    
    void Obstacle::SetCaption(string caption)
    {
         _caption = caption;
    }
    
    double Obstacle::GetHeight() const
    {
         return _height;
    }
    
    void Obstacle::SetHeight(double height)
    {
         _height = height;
    }
    
    int Obstacle::GetId() const
    {
         return _id;
    }
    
    void Obstacle::SetId(int id)
    {
         _id = id;
    }
    
    const vector<Point>& Obstacle::GetPolygon() const
    {
         return _poly;
    }
    
    string Obstacle::Write()
    {
         string s;
    
         for (unsigned int j = 0; j < _walls.size(); j++) {
              const Wall& w = _walls[j];
              s.append(w.Write());
              //pos = pos + w.GetPoint1() + w.GetPoint2();
         }
         //pos = pos * (0.5 / _walls.size());
    
         Point pos = GetCentroid();
    
         //add the obstacle caption
         char tmp[CLENGTH];
         //sprintf(tmp, "\t\t<label centerX=\"%.2f\" centerY=\"%.2f\" centerZ=\"0\" text=\"%s\" color=\"100\" />\n"
         //              , pos.GetX() * FAKTOR, pos.GetY() * FAKTOR, _caption.c_str());
    
         sprintf(tmp, "\t\t<label centerX=\"%.2f\" centerY=\"%.2f\" centerZ=\"0\" text=\"%d\" color=\"100\" />\n"
                 , pos.GetX() * FAKTOR, pos.GetY() * FAKTOR, _id);
         s.append(tmp);
    
         return s;
    }
    
    const vector<Wall>& Obstacle::GetAllWalls() const
    {
         return _walls;
    }
    
    int Obstacle::WhichQuad(const Point& vertex, const Point& hitPos) const
    {
         return (vertex.GetX() > hitPos.GetX()) ?
                   ((vertex.GetY() > hitPos.GetY()) ? 1 : 4) :
                   ((vertex.GetY() > hitPos.GetY()) ? 2 : 3);
    
    //     if ((vertex.GetX() - hitPos.GetX())>J_EPS)
    //     {
    //          if ((vertex.GetY() - hitPos.GetY())>J_EPS)
    //          {
    //               return 1;
    //          } else
    //          {
    //               return 4;
    //          }
    //     } else
    //     {
    //          if ((vertex.GetY() - hitPos.GetY())>J_EPS)
    //          {
    //               return 2;
    //          } else
    //          {
    //               return 3;
    //          }
    //
    //     }
    
    }
    
    // x-Koordinate der Linie von einer Eccke zur nächsten
    double Obstacle::Xintercept(const Point& point1, const Point& point2, double hitY) const
    {
         return (point2.GetX() - (((point2.GetY() - hitY) * (point1.GetX() - point2.GetX())) /
                                  (point1.GetY() - point2.GetY())));
    }
    
    
    bool Obstacle::Contains(const Point& ped) const
    {
         //case when the point is on an edge
         // todo: this affect the runtime, and do we really need that
         // If we do not d othis check, then for a square for instance, half the points located on the edge will be inside and
         // the other half will be outside the polygon.
         for(auto& w: _walls)
         {
              if(w.IsInLineSegment(ped)) return true;
         }
         // in the case the obstacle is not a close surface, allow
         // pedestrians distribution 'inside'
    
         short edge, first, next;
         short quad, next_quad, delta, total;
    
         /////////////////////////////////////////////////////////////
         edge = first = 0;
         quad = WhichQuad(_poly[edge], ped);
         total = 0; // COUNT OF ABSOLUTE SECTORS CROSSED
         /* LOOP THROUGH THE VERTICES IN A SECTOR */
         do {
              next = (edge + 1) % _poly.size();
              next_quad = WhichQuad(_poly[next], ped);
              delta = next_quad - quad; // HOW MANY QUADS HAVE I MOVED
    
              // SPECIAL CASES TO HANDLE CROSSINGS OF MORE THEN ONE
              //QUAD
    
              switch (delta) {
              case 2: // IF WE CROSSED THE MIDDLE, FIGURE OUT IF IT
                   //WAS CLOCKWISE OR COUNTER
              case -2: // US THE X POSITION AT THE HIT POINT TO
                   // DETERMINE WHICH WAY AROUND
                   if (Xintercept(_poly[edge], _poly[next], ped.GetY()) > ped.GetX())
                        delta = -(delta);
                   break;
              case 3: // MOVING 3 QUADS IS LIKE MOVING BACK 1
                   delta = -1;
                   break;
              case -3: // MOVING BACK 3 IS LIKE MOVING FORWARD 1
                   delta = 1;
                   break;
              }
              /* ADD IN THE DELTA */
              total += delta;
              quad = next_quad; // RESET FOR NEXT STEP
              edge = next;
         } while (edge != first);
    
         /* AFTER ALL IS DONE IF THE TOTAL IS 4 THEN WE ARE INSIDE */
         if (abs(total) == 4)
              return true;
         else
              return false;
    }
    
    
    bool Obstacle::ConvertLineToPoly()
    {
         vector<Line*> copy;
         vector<Point> tmpPoly;
         Point point;
         Line* line;
         // Alle Linienelemente in copy speichern
         for(auto& w: _walls)
         {
              copy.push_back(&w);
         }
    
         line = copy[0];
         tmpPoly.push_back(line->GetPoint1());
         point = line->GetPoint2();
         copy.erase(copy.begin());
         // Polygon aus allen Linen erzeugen
         for (int i = 0; i < (int) copy.size(); i++) {
              line = copy[i];
              if ((point - line->GetPoint1()).Norm() < J_TOLERANZ) {
                   tmpPoly.push_back(line->GetPoint1());
                   point = line->GetPoint2();
                   copy.erase(copy.begin() + i);
                   // von vorne suchen
                   i = -1;
              } else if ((point - line->GetPoint2()).Norm() < J_TOLERANZ) {
                   tmpPoly.push_back(line->GetPoint2());
                   point = line->GetPoint1();
                   copy.erase(copy.begin() + i);
                   // von vorne suchen
                   i = -1;
              }
         }
         if ((tmpPoly[0] - point).Norm() > J_TOLERANZ) {
              char tmp[CLENGTH];
              sprintf(tmp, "ERROR: \tObstacle::ConvertLineToPoly(): ID %d !!!\n", _id);
              Log->Write(tmp);
              sprintf(tmp, "ERROR: \tDistance between the points: %lf !!!\n", (tmpPoly[0] - point).Norm());
              Log->Write(tmp);
              return false;
         }
         _poly = tmpPoly;
    
    
         //check if all walls and goals were used in the polygon
         for (const auto& w: _walls)
         {
              for (const auto & ptw: {w.GetPoint1(),w.GetPoint2()})
              {
                   if(IsPartOfPolygon(ptw)==false)
                   {
                        Log->Write("ERROR:\t Edge was not used during polygon creation for obstacle: %s",w.toString().c_str());
                        return false;
                   }
              }
         }
         return true;
    }
    
    const Point Obstacle::GetCentroid() const
    {
    
         double px=0,py=0;
         double signedArea = 0.0;
         double x0 = 0.0; // Current vertex X
         double y0 = 0.0; // Current vertex Y
         double x1 = 0.0; // Next vertex X
         double y1 = 0.0; // Next vertex Y
         double a = 0.0;  // Partial signed area
    
         // For all vertices except last
         unsigned int i=0;
         for (i=0; i<_poly.size()-1; ++i) {
              x0 = _poly[i].GetX();
              y0 = _poly[i].GetY();
              x1 = _poly[i+1].GetX();
              y1 = _poly[i+1].GetY();
              a = x0*y1 - x1*y0;
              signedArea += a;
              px += (x0 + x1)*a;
              py += (y0 + y1)*a;
         }
    
         // Do last vertex
         x0 = _poly[i].GetX();
         y0 = _poly[i].GetY();
         x1 = _poly[0].GetX();
         y1 = _poly[0].GetY();
         a = x0*y1 - x1*y0;
         signedArea += a;
         px += (x0 + x1)*a;
         py += (y0 + y1)*a;
    
         signedArea *= 0.5;
         px /= (6*signedArea);
         py /= (6*signedArea);
    
         return Point (px,py);
    }
    
    bool Obstacle::IsClockwise() const
    {
         if(_poly.size()<3) {
              Log->Write("ERROR:\tYou need at least 3 vertices to check for orientation. Subroom ID [%d]");
              return false;
              //exit(EXIT_FAILURE);
         }
    
         Point vecAB= _poly[1]-_poly[0];
         Point vecBC= _poly[2]-_poly[1];
    
         double det= vecAB.Determinant(vecBC);
         if(fabs(det)<J_EPS) det=0.0;
    
         return ( det<=0.0 );
    }
    
    bool Obstacle::IntersectWithLine(const Line& line) const
    {
    
         for (unsigned int i=0; i<_walls.size(); i++) {
    
              if(_walls[i].IntersectionWith(line)) return true;
         }
    
         return false;
    }
    
    bool Obstacle::IsPartOfPolygon(const Point& ptw)
    {
         if ( false == IsElementInVector(_poly, ptw))
         {
              //maybe the point was too closed to other points and got replaced
              //check that eventuality
              bool near = false;
              for (const auto & pt : _poly)
              {
                   if ((pt - ptw).Norm() < J_TOLERANZ)
                   {
                        near = true;
                        break;
                   }
              }
    
              if(near==false)
              {
                   return false;
              }
         }
         return true;
    }