Building.cpp 46.7 KB
Newer Older
1
/**
Weichen's avatar
Weichen committed
2 3
 * \file        Building.cpp
 * \date        Oct 1, 2014
4 5
 * \version     v0.7
 * \copyright   <2009-2015> Forschungszentrum Jülich GmbH. All rights reserved.
Ulrich Kemloh's avatar
Ulrich Kemloh committed
6
 *
Weichen's avatar
Weichen committed
7
 * \section License
8 9 10
 * This file is part of JuPedSim.
 *
 * JuPedSim is free software: you can redistribute it and/or modify
Weichen's avatar
Weichen committed
11
 * it under the terms of the GNU Lesser General Public License as published by
12 13 14 15 16 17 18 19
 * 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.
 *
Weichen's avatar
Weichen committed
20
 * You should have received a copy of the GNU Lesser General Public License
21 22
 * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>.
 *
Weichen's avatar
Weichen committed
23
 * \section Description
24 25
 *
 *
Weichen's avatar
Weichen committed
26 27
 **/

Ulrich Kemloh's avatar
Ulrich Kemloh committed
28 29

#include "Building.h"
GrgrLmml's avatar
GrgrLmml committed
30

Ulrich Kemloh's avatar
Ulrich Kemloh committed
31
#include "../geometry/SubRoom.h"
Ulrich Kemloh's avatar
Ulrich Kemloh committed
32
#include "../tinyxml/tinyxml.h"
33 34

#ifdef _SIMULATOR
GrgrLmml's avatar
GrgrLmml committed
35 36

#include "GeometryReader.h"
Ulrich Kemloh's avatar
Ulrich Kemloh committed
37 38
#include "../pedestrian/Pedestrian.h"
#include "../mpi/LCGrid.h"
GrgrLmml's avatar
GrgrLmml committed
39
#include "../IO/GeoFileParser.h"
40 41 42
#include <boost/filesystem.hpp>
//namespace fs = std::experimental::filesystem;
namespace fs = boost::filesystem;
GrgrLmml's avatar
GrgrLmml committed
43

44
#endif
45
//#undef _OPENMP
Ulrich Kemloh's avatar
Ulrich Kemloh committed
46 47

#ifdef _OPENMP
GrgrLmml's avatar
GrgrLmml committed
48

49
#else
Mohcine Chraibi's avatar
Mohcine Chraibi committed
50 51
#define omp_get_thread_num()    0
#define omp_get_max_threads()   1
Ulrich Kemloh's avatar
Ulrich Kemloh committed
52
#endif
53
#define DEBUG 0
Ulrich Kemloh's avatar
Ulrich Kemloh committed
54

55
using namespace std;
Ulrich Kemloh's avatar
Ulrich Kemloh committed
56

57 58 59
Building::Building()
{
     _caption = "no_caption";
GrgrLmml's avatar
GrgrLmml committed
60
     _geometryFilename = "";
61 62 63 64
     _routingEngine = nullptr;
     _linkedCellGrid = nullptr;
     _savePathway = false;
}
Ulrich Kemloh's avatar
Ulrich Kemloh committed
65

66
#ifdef _SIMULATOR
GrgrLmml's avatar
GrgrLmml committed
67

Arne Graf's avatar
Arne Graf committed
68
Building::Building(Configuration* configuration, PedDistributor& pedDistributor)
GrgrLmml's avatar
GrgrLmml committed
69 70
          :_configuration(configuration),
           _routingEngine(
Mohcine Chraibi's avatar
Mohcine Chraibi committed
71 72
                 configuration->GetRoutingEngine()),
           _caption("no_caption")
Oliver Schmidts's avatar
Oliver Schmidts committed
73 74
{
     _savePathway = false;
Ulrich Kemloh's avatar
Ulrich Kemloh committed
75
     _linkedCellGrid = nullptr;
76

GrgrLmml's avatar
GrgrLmml committed
77 78
#ifdef _JPS_AS_A_SERVICE
     if (_configuration->GetRunAsService()) {
Mohcine Chraibi's avatar
Mohcine Chraibi committed
79 80
           std::unique_ptr<GeometryFromProtobufLoader> parser(new GeometryFromProtobufLoader(_configuration));
           parser->LoadBuilding(this);
81
     }
GrgrLmml's avatar
GrgrLmml committed
82 83
     else
#endif
84
     {
Mohcine Chraibi's avatar
Mohcine Chraibi committed
85 86
           std::unique_ptr<GeoFileParser> parser(new GeoFileParser(_configuration));
           parser->LoadBuilding(this);
87 88
     }

GrgrLmml's avatar
GrgrLmml committed
89
     if (!InitGeometry()) {
90
          Log->Write("ERROR:\t could not initialize the geometry!");
GrgrLmml's avatar
GrgrLmml committed
91
          exit(EXIT_FAILURE);
92
     }
93

94

95

GrgrLmml's avatar
GrgrLmml committed
96 97 98
     //TODO: check whether traffic info can be loaded before InitGeometry if so call it in LoadBuilding instead and make
     //TODO: LoadTrafficInfo private [gl march '16]

99

GrgrLmml's avatar
GrgrLmml committed
100
     if (!pedDistributor.Distribute(this)) {
Mohcine Chraibi's avatar
Mohcine Chraibi committed
101
          Log->Write("ERROR:\tcould not distribute the pedestrians\n");
GrgrLmml's avatar
GrgrLmml committed
102
          exit(EXIT_FAILURE);
103
     }
GrgrLmml's avatar
GrgrLmml committed
104
     InitGrid();
105

GrgrLmml's avatar
GrgrLmml committed
106
     if (!_routingEngine->Init(this)) {
107
          Log->Write("ERROR:\t could not initialize the routers!");
GrgrLmml's avatar
GrgrLmml committed
108
          exit(EXIT_FAILURE);
109 110
     }

GrgrLmml's avatar
GrgrLmml committed
111
     if (!SanityCheck()) {
112
          Log->Write("ERROR:\t There are sanity errors in the geometry file");
GrgrLmml's avatar
GrgrLmml committed
113
          exit(EXIT_FAILURE);
114 115
     }

GrgrLmml's avatar
GrgrLmml committed
116
//     SaveGeometry("/home/laemmel/Desktop/geo.xml");
Oliver Schmidts's avatar
Oliver Schmidts committed
117
}
GrgrLmml's avatar
GrgrLmml committed
118

119
#endif
Ulrich Kemloh's avatar
Ulrich Kemloh committed
120

121 122
Building::~Building()
{
123 124 125
     //
     // for (int i = 0; i < GetNumberOfRooms(); i++)
     //    delete _rooms[i];
Ulrich Kemloh's avatar
Ulrich Kemloh committed
126

127
#ifdef _SIMULATOR
GrgrLmml's avatar
GrgrLmml committed
128
     for (unsigned int p = 0; p<_allPedestians.size(); p++) {
129
          delete _allPedestians[p];
130 131 132
     }
     _allPedestians.clear();
     delete _linkedCellGrid;
133
#endif
Ulrich Kemloh's avatar
Ulrich Kemloh committed
134

135 136 137 138
     if (_pathWayStream.is_open())
          _pathWayStream.close();

     for (map<int, Crossing*>::const_iterator iter = _crossings.begin();
GrgrLmml's avatar
GrgrLmml committed
139
          iter!=_crossings.end(); ++iter) {
140 141 142
          delete iter->second;
     }
     for (map<int, Transition*>::const_iterator iter = _transitions.begin();
GrgrLmml's avatar
GrgrLmml committed
143
          iter!=_transitions.end(); ++iter) {
144 145 146
          delete iter->second;
     }
     for (map<int, Hline*>::const_iterator iter = _hLines.begin();
GrgrLmml's avatar
GrgrLmml committed
147
          iter!=_hLines.end(); ++iter) {
148 149 150
          delete iter->second;
     }
     for (map<int, Goal*>::const_iterator iter = _goals.begin();
GrgrLmml's avatar
GrgrLmml committed
151
          iter!=_goals.end(); ++iter) {
152 153
          delete iter->second;
     }
Ulrich Kemloh's avatar
Ulrich Kemloh committed
154 155
}

Arne Graf's avatar
Arne Graf committed
156
Configuration* Building::GetConfig() const {
Arne Graf's avatar
Arne Graf committed
157 158 159
     return _configuration;
}

GrgrLmml's avatar
GrgrLmml committed
160 161 162
///************************************************************
// setters
// ************************************************************/
163 164 165
void Building::SetCaption(const std::string& s)
{
     _caption = s;
Ulrich Kemloh's avatar
Ulrich Kemloh committed
166 167 168
}

/*************************************************************
GrgrLmml's avatar
GrgrLmml committed
169
 getters
Ulrich Kemloh's avatar
Ulrich Kemloh committed
170 171
 ************************************************************/

172 173 174
string Building::GetCaption() const
{
     return _caption;
Ulrich Kemloh's avatar
Ulrich Kemloh committed
175 176
}

177 178
RoutingEngine* Building::GetRoutingEngine() const
{
GrgrLmml's avatar
GrgrLmml committed
179
     return _configuration->GetRoutingEngine().get();
Ulrich Kemloh's avatar
Ulrich Kemloh committed
180 181
}

182 183
int Building::GetNumberOfRooms() const
{
GrgrLmml's avatar
GrgrLmml committed
184
     return (int) _rooms.size();
Ulrich Kemloh's avatar
Ulrich Kemloh committed
185 186
}

187 188
int Building::GetNumberOfGoals() const
{
GrgrLmml's avatar
GrgrLmml committed
189
     return (int) (_transitions.size()+_hLines.size()+_crossings.size());
190 191
}

192
const std::map<int, std::shared_ptr<Room> >& Building::GetAllRooms() const
193 194
{
     return _rooms;
Ulrich Kemloh's avatar
Ulrich Kemloh committed
195 196
}

197 198
Room* Building::GetRoom(int index) const
{
199
     //todo: obsolete since the check is done by .at()
GrgrLmml's avatar
GrgrLmml committed
200 201
     if (_rooms.count(index)==0) {
          Log->Write("ERROR: Wrong 'index' in CBuiling::GetRoom() Room ID: %d size: %d", index, _rooms.size());
Mohcine Chraibi's avatar
Mohcine Chraibi committed
202
          Log->Write("\tControl your rooms ID and make sure they are in the order 0, 1, 2,.. ");
203
          return nullptr;
204
     }
205 206
     //return _rooms[index];
     return _rooms.at(index).get();
Ulrich Kemloh's avatar
Ulrich Kemloh committed
207 208
}

209 210 211
LCGrid* Building::GetGrid() const
{
     return _linkedCellGrid;
Ulrich Kemloh's avatar
Ulrich Kemloh committed
212 213
}

214 215
void Building::AddRoom(Room* room)
{
216
     _rooms[room->GetID()] = std::shared_ptr<Room>(room);
Ulrich Kemloh's avatar
Ulrich Kemloh committed
217 218
}

219 220 221 222 223 224 225 226 227 228 229
void Building::AddSurroundingRoom()
{
     Log->Write("INFO: \tAdding the room 'outside' ");
     // first look for the geometry boundaries
     double x_min = FLT_MAX;
     double x_max = -FLT_MAX;
     double y_min = FLT_MAX;
     double y_max = -FLT_MAX;
     //finding the bounding of the grid
     // and collect the pedestrians

GrgrLmml's avatar
GrgrLmml committed
230 231 232
     for (auto&& itr_room: _rooms) {
          for (auto&& itr_subroom: itr_room.second->GetAllSubRooms()) {
               for (auto&& wall:itr_subroom.second->GetAllWalls()) {
Oliver Schmidts's avatar
Oliver Schmidts committed
233 234 235 236
                    double x1 = wall.GetPoint1()._x;
                    double y1 = wall.GetPoint1()._y;
                    double x2 = wall.GetPoint2()._x;
                    double y2 = wall.GetPoint2()._y;
237

GrgrLmml's avatar
GrgrLmml committed
238 239 240 241
                    double xmax = (x1>x2) ? x1 : x2;
                    double xmin = (x1>x2) ? x2 : x1;
                    double ymax = (y1>y2) ? y1 : y2;
                    double ymin = (y1>y2) ? y2 : y1;
242

GrgrLmml's avatar
GrgrLmml committed
243 244 245 246
                    x_min = (xmin<=x_min) ? xmin : x_min;
                    x_max = (xmax>=x_max) ? xmax : x_max;
                    y_max = (ymax>=y_max) ? ymax : y_max;
                    y_min = (ymin<=y_min) ? ymin : y_min;
247 248 249 250
               }
          }
     }

GrgrLmml's avatar
GrgrLmml committed
251 252
     for (auto&& itr_goal:_goals) {
          for (auto&& wall: itr_goal.second->GetAllWalls()) {
Oliver Schmidts's avatar
Oliver Schmidts committed
253 254 255 256
               double x1 = wall.GetPoint1()._x;
               double y1 = wall.GetPoint1()._y;
               double x2 = wall.GetPoint2()._x;
               double y2 = wall.GetPoint2()._y;
257

GrgrLmml's avatar
GrgrLmml committed
258 259 260 261
               double xmax = (x1>x2) ? x1 : x2;
               double xmin = (x1>x2) ? x2 : x1;
               double ymax = (y1>y2) ? y1 : y2;
               double ymin = (y1>y2) ? y2 : y1;
262

GrgrLmml's avatar
GrgrLmml committed
263 264 265 266
               x_min = (xmin<=x_min) ? xmin : x_min;
               x_max = (xmax>=x_max) ? xmax : x_max;
               y_max = (ymax>=y_max) ? ymax : y_max;
               y_min = (ymin<=y_min) ? ymin : y_min;
267 268 269
          }
     }
     //make the grid slightly larger.
GrgrLmml's avatar
GrgrLmml committed
270 271 272 273
     x_min = x_min-10.0;
     x_max = x_max+10.0;
     y_min = y_min-10.0;
     y_max = y_max+10.0;
274 275

     SubRoom* bigSubroom = new NormalSubRoom();
276
     bigSubroom->SetRoomID((int) _rooms.size());
277 278 279 280 281 282
     bigSubroom->SetSubRoomID(0); // should be the single subroom
     bigSubroom->AddWall(Wall(Point(x_min, y_min), Point(x_min, y_max)));
     bigSubroom->AddWall(Wall(Point(x_min, y_max), Point(x_max, y_max)));
     bigSubroom->AddWall(Wall(Point(x_max, y_max), Point(x_max, y_min)));
     bigSubroom->AddWall(Wall(Point(x_max, y_min), Point(x_min, y_min)));

GrgrLmml's avatar
GrgrLmml committed
283
     Room* bigRoom = new Room();
284 285
     bigRoom->AddSubRoom(bigSubroom);
     bigRoom->SetCaption("outside");
286
     bigRoom->SetID((int) _rooms.size());
287
     AddRoom(bigRoom);
Ulrich Kemloh's avatar
Ulrich Kemloh committed
288 289
}

290
bool Building::InitGeometry()
291 292
{
     Log->Write("INFO: \tInit Geometry");
293
     correct();
GrgrLmml's avatar
GrgrLmml committed
294 295
     for (auto&& itr_room: _rooms) {
          for (auto&& itr_subroom: itr_room.second->GetAllSubRooms()) {
296
               //create a close polyline out of everything
297 298
               vector<Line*> goals = vector<Line*>();

299
               //  collect all crossings
GrgrLmml's avatar
GrgrLmml committed
300
               for (auto&& cros:itr_subroom.second->GetAllCrossings()) {
301
                    goals.push_back(cros);
302
               }
303
               //collect all transitions
GrgrLmml's avatar
GrgrLmml committed
304
               for (auto&& trans:itr_subroom.second->GetAllTransitions()) {
305
                    goals.push_back(trans);
306 307
               }
               // initialize the poly
GrgrLmml's avatar
GrgrLmml committed
308
               if (!itr_subroom.second->ConvertLineToPoly(goals))
309 310
                    return false;
               itr_subroom.second->CalculateArea();
311 312

               //do the same for the obstacles that are closed
GrgrLmml's avatar
GrgrLmml committed
313
               for (auto&& obst:itr_subroom.second->GetAllObstacles()) {
314
                    //if (obst->GetClosed() == 1)
GrgrLmml's avatar
GrgrLmml committed
315
                    if (!obst->ConvertLineToPoly())
316
                         return false;
317
               }
318

319 320 321
               //here we can create a boost::geometry::model::polygon out of the vector<Point> objects created above
               itr_subroom.second->CreateBoostPoly();

322 323
               double minElevation = FLT_MAX;
               double maxElevation = -FLT_MAX;
GrgrLmml's avatar
GrgrLmml committed
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
               for (auto&& wall:itr_subroom.second->GetAllWalls()) {
                    const Point& P1 = wall.GetPoint1();
                    const Point& P2 = wall.GetPoint2();
                    if (minElevation>itr_subroom.second->GetElevation(P1)) {
                         minElevation = itr_subroom.second->GetElevation(P1);
                    }

                    if (maxElevation<itr_subroom.second->GetElevation(P1)) {
                         maxElevation = itr_subroom.second->GetElevation(P1);
                    }

                    if (minElevation>itr_subroom.second->GetElevation(P2)) {
                         minElevation = itr_subroom.second->GetElevation(P2);
                    }

                    if (maxElevation<itr_subroom.second->GetElevation(P2)) {
                         maxElevation = itr_subroom.second->GetElevation(P2);
                    }
Mohcine Chraibi's avatar
Mohcine Chraibi committed
342 343 344
               }
               itr_subroom.second->SetMaxElevation(maxElevation);
               itr_subroom.second->SetMinElevation(minElevation);
345 346
          }
     }
347

Mohcine Chraibi's avatar
Mohcine Chraibi committed
348

Ulrich Kemloh's avatar
Ulrich Kemloh committed
349 350 351
     // look and save the neighbor subroom for improving the runtime
     // that information is already present in the crossing/transitions

GrgrLmml's avatar
GrgrLmml committed
352 353 354 355 356
     for (const auto& cross: _crossings) {
          SubRoom* s1 = cross.second->GetSubRoom1();
          SubRoom* s2 = cross.second->GetSubRoom2();
          if (s1) s1->AddNeighbor(s2);
          if (s2) s2->AddNeighbor(s1);
Ulrich Kemloh's avatar
Ulrich Kemloh committed
357 358
     }

GrgrLmml's avatar
GrgrLmml committed
359 360 361 362 363
     for (const auto& trans: _transitions) {
          SubRoom* s1 = trans.second->GetSubRoom1();
          SubRoom* s2 = trans.second->GetSubRoom2();
          if (s1) s1->AddNeighbor(s2);
          if (s2) s2->AddNeighbor(s1);
Ulrich Kemloh's avatar
Ulrich Kemloh committed
364 365
     }

366
     Log->Write("INFO: \tInit Geometry successful!!!\n");
367 368

     return true;
Ulrich Kemloh's avatar
Ulrich Kemloh committed
369 370
}

371
bool Building::correct() const {
Mohcine Chraibi's avatar
Mohcine Chraibi committed
372
     Log->Write("INFO:\tenter correct ...");
373 374
     bool removed = false;

375 376
     for(auto&& room: this->GetAllRooms()) {
          for(auto&& subroom: room.second->GetAllSubRooms()) {
Mohcine Chraibi's avatar
Mohcine Chraibi committed
377
                // -- remove exits *on* walls
378
                removed = RemoveOverlappingDoors(subroom.second);
Mohcine Chraibi's avatar
Mohcine Chraibi committed
379 380 381 382 383 384 385
               // --------------------------
               // -- remove overlapping walls
               auto walls = subroom.second->GetAllWalls(); // this call
                                                                // should be
                                                                // after
                                                                // eliminating
                                                                // nasty exits
386
#if DEBUG
387
               std::cout<< "\n" << KRED << "correct Room " << room.first << "  Subroom " << subroom.first << RESET  << std::endl;
388
#endif
389
               for(auto const & bigWall: walls) //self checking
390
               {
Mohcine Chraibi's avatar
Mohcine Chraibi committed
391 392
                    // std::cout << "BigWall: " << std::endl;
                      // bigWall.WriteToErrorLog();
Mohcine Chraibi's avatar
Mohcine Chraibi committed
393 394
                    //special treatment for doors
/////
395 396 397 398
                    std::vector<Wall> WallPieces;
                    WallPieces = SplitWall(subroom.second, bigWall);
                    if(!WallPieces.empty())
                         removed = true;
399
#if DEBUG
Mohcine Chraibi's avatar
Mohcine Chraibi committed
400
z                    std::cout << "Wall pieces size : " <<  WallPieces.size() << std::endl;
Mohcine Chraibi's avatar
Mohcine Chraibi committed
401 402
                    for(auto w:WallPieces)
                         w.WriteToErrorLog();
Mohcine Chraibi's avatar
Mohcine Chraibi committed
403
#endif
404 405 406 407 408
                    int ok=0;
                    while(!ok)
                    {
                         ok = 1; // ok ==1 means no new pieces are found
                         for (auto wallPiece: WallPieces)
409
                         {
410 411
                              std::vector<Wall> tmpWallPieces;
                              tmpWallPieces = SplitWall(subroom.second, wallPiece);
412 413 414 415 416 417 418 419 420 421 422
                              if(!tmpWallPieces.empty())
                              {
                                   // std::cout << "set ok because tmp size =" << tmpWallPieces.size() << std::endl;
                                    ok = 0; /// stay in the loop
                                    // append tmpWallPieces to WallPiece
                                    WallPieces.insert(std::end(WallPieces),std::begin(tmpWallPieces), std::end(tmpWallPieces));
                                    // remove the line since it was split already
                                    auto it = std::find(WallPieces.begin(), WallPieces.end(), wallPiece);
                                    if (it != WallPieces.end())
                                    {
                                         // std::cout<< KGRN << "delete wall ..." << RESET <<std::endl;
Mohcine Chraibi's avatar
Mohcine Chraibi committed
423
                                         // wallPiece.WriteToErrorLog();
424 425 426 427
                                         WallPieces.erase(it);
                                    }

                                    // std::cout << "BNow Wall peces size : " <<  WallPieces.size() << std::endl;
428 429
                              }
                         }
430 431
#if DEBUG
                         std::cout << "ok "<< ok << std::endl;
432 433
                         std::cout << "new while  Wall peces size : " <<  WallPieces.size() << std::endl;
                         std::cout << "====" << std::endl;
434

435 436 437 438
                         for(auto t: WallPieces){
                              std::cout << ">> Piece: " << std::endl;
                              t.WriteToErrorLog();
                         }
439 440
#endif
                         // getc(stdin);
441 442 443 444 445 446 447 448 449 450 451 452
                    }// while
                    // remove
                    // duplicates fromWllPiecs
                    if(!WallPieces.empty())
                    {
                         //remove  duplicaes from wallPiecess

                         auto end = WallPieces.end();
                         for (auto it = WallPieces.begin(); it != end; ++it) {
                                end = std::remove(it + 1, end, *it);
                         }
                         WallPieces.erase(end, WallPieces.end());
453 454
#if DEBUG
                         std::cout << "..removing duplicates pieces..\n";
455 456 457 458
                         for(auto t: WallPieces){
                              std::cout << ">>>> Piece: " << std::endl;
                              t.WriteToErrorLog();
                         }
459
#endif
460 461 462 463
                         // remove big wall and add one wallpiece to walls
                         ReplaceBigWall(subroom.second, bigWall, WallPieces);
                    }
               }// bigLine
464 465
          }//s
     }//r
466 467

     if(removed)
468 469
     {
          fs::path f("correct_"+this->GetConfig()->GetGeometryFile());
470 471 472
          //fs::path p(this->GetConfig()->GetProjectRootDir());
          //p = p / f;
          std::string filename = f.string();
473 474
          if(SaveGeometry(filename))
               this->GetConfig()->SetGeometryFile(filename);
475
     }
Mohcine Chraibi's avatar
Mohcine Chraibi committed
476
     Log->Write("INFO:\tLeave geometry correct with success .. maybe");
477

478 479
     return true;
}
Mohcine Chraibi's avatar
Mohcine Chraibi committed
480 481
bool Building::RemoveOverlappingDoors(const std::shared_ptr<SubRoom>& subroom) const
{
482
#if DEBUG
483
     std::cout << KRED << "\nEnter RemoveOverlappingDoors with subroom " << subroom->GetRoomID() << "," << subroom->GetSubRoomID() << RESET<<"\n";
484
#endif
485
     bool removed = false; // did we remove anything?
486 487 488 489
      vector<Line> exits = vector<Line>(); // transitions+crossings
      auto walls = subroom->GetAllWalls();
      vector<Wall> tmpWalls = vector<Wall>(); //splited big walls are stored here
      bool isBigWall = false; // mark walls as big. If not big, add them to tmpWalls
Mohcine Chraibi's avatar
Mohcine Chraibi committed
490 491 492 493 494 495
      //  collect all crossings
      for (auto&& cros: subroom->GetAllCrossings())
            exits.push_back(*cros);
      //collect all transitions
      for (auto&& trans: subroom->GetAllTransitions())
            exits.push_back(*trans);
496 497
#if DEBUG
      std::cout << "subroom walls: \n";
498 499 500
      for(auto w: subroom->GetAllWalls())
            w.WriteToErrorLog();
      std::cout << "---------------\n";
Mohcine Chraibi's avatar
Mohcine Chraibi committed
501
      // removing doors on walls
502
#endif
503 504 505 506 507 508 509 510 511 512 513 514
      while(!walls.empty())
      {
           auto wall = walls.back();
           walls.pop_back();
           isBigWall = false;
           for(auto  e=exits.begin(); e!=exits.end(); )
           {
                if(wall.NearlyInLineSegment(e->GetPoint1()) && wall.NearlyInLineSegment(e->GetPoint2()))
                {
                     isBigWall = true; // mark walls as big
                     double dist_pt1 = (wall.GetPoint1() - e->GetPoint1()).NormSquare();
                     double dist_pt2 = (wall.GetPoint1() - e->GetPoint2()).NormSquare();
Mohcine Chraibi's avatar
Mohcine Chraibi committed
515 516
                     Point A, B;

517 518
                     if(dist_pt1<dist_pt2)
                     {
Mohcine Chraibi's avatar
Mohcine Chraibi committed
519 520
                          A = e->GetPoint1();
                          B = e->GetPoint2();
521 522 523
                     }
                     else
                     {
Mohcine Chraibi's avatar
Mohcine Chraibi committed
524 525
                          A = e->GetPoint2();
                          B = e->GetPoint1();
526
                     }
Mohcine Chraibi's avatar
Mohcine Chraibi committed
527 528 529

                     Wall NewWall(wall.GetPoint1(), A);
                     Wall NewWall1(wall.GetPoint2(), B);
Mohcine Chraibi's avatar
Mohcine Chraibi committed
530 531
                     // NewWall.WriteToErrorLog();
                     // NewWall1.WriteToErrorLog();
Mohcine Chraibi's avatar
Mohcine Chraibi committed
532 533 534
                     // add new lines to be controled against overlap with exits
                     walls.push_back(NewWall);
                     walls.push_back(NewWall1);
535 536
                     subroom->RemoveWall(wall);
                     exits.erase(e); // we don't need to check this exit again
537
                     removed = true;
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552
                     break; // we are done with this wall. get next wall.

                }// if
                else
                {
                     e++;
                }
           } // exits
           if(!isBigWall)
                tmpWalls.push_back(wall);

      }// while

      // copy walls in subroom
      for(auto const & wall: tmpWalls)
Mohcine Chraibi's avatar
Mohcine Chraibi committed
553
      {
554
           subroom->AddWall(wall);
Mohcine Chraibi's avatar
Mohcine Chraibi committed
555
      }
556

557
#if DEBUG
558 559 560 561
      std::cout << "\nnew Subroom:  " << std::endl;
      for(auto w: subroom->GetAllWalls())
           w.WriteToErrorLog(); // AddWall won't add existing walls

562
      std::cout << KGRN << "\nLEAVE with removed=:   "<< removed << RESET << std::endl;
563 564
      getc(stdin);
#endif
565

566
      return removed;
Mohcine Chraibi's avatar
Mohcine Chraibi committed
567
}
568

569 570
std::vector<Wall>  Building::SplitWall(const std::shared_ptr<SubRoom>& subroom, const Wall&  bigWall) const{
     std::vector<Wall> WallPieces;
571
#if DEBUG
572 573
     std::cout << subroom->GetSubRoomID() << "collect wall pieces with " << std::endl;
     bigWall.WriteToErrorLog();
Mohcine Chraibi's avatar
Mohcine Chraibi committed
574
#endif
575 576 577 578 579
     auto walls = subroom->GetAllWalls();
     auto crossings = subroom->GetAllCrossings();
     auto transitions = subroom->GetAllTransitions();
     // TODO: Hlines too?
     vector<Line> walls_and_exits = vector<Line>();
Mohcine Chraibi's avatar
Mohcine Chraibi committed
580
     // @todo: check if this is GetAllGoals()?
581 582 583 584 585 586 587 588 589 590
     //  collect all crossings
     for (auto&& cros:crossings)
          walls_and_exits.push_back(*cros);
     //collect all transitions
     for (auto&& trans: transitions)
          walls_and_exits.push_back(*trans);
     for (auto&& wall: walls)
          walls_and_exits.push_back(wall);

     for(auto const & other: walls_and_exits)
591
     {
592
#if DEBUG
Mohcine Chraibi's avatar
Mohcine Chraibi committed
593
          std::cout << other.toString() << "\n";
594
#endif
595 596
          if((bigWall == other) || (bigWall.ShareCommonPointWith(other))) continue;
          Point intersectionPoint;
597

598 599 600
          if(bigWall.IntersectionWith(other, intersectionPoint))
          {
               if(intersectionPoint == bigWall.GetPoint1() || intersectionPoint == bigWall.GetPoint2()) continue;
601
#if DEBUG
602
               std::cout << "BIG\n";
603 604
               std::cout << bigWall.GetPoint1()._x << " " << bigWall.GetPoint1()._y << "\n";
               std::cout << bigWall.GetPoint2()._x << " " << bigWall.GetPoint2()._y << "\n";
Mohcine Chraibi's avatar
Mohcine Chraibi committed
605 606
               std::cout<< "intersectin with: " << std::endl;
               std::cout << other.toString() << "\n";
607
               std::cout << intersectionPoint._x <<" " <<intersectionPoint._y << "\n";
Mohcine Chraibi's avatar
Mohcine Chraibi committed
608
               string s = intersectionPoint.toString();
609 610 611
               std::cout << "\t >> Intersection at Point: " << s.c_str() << "\n";
#endif
               //Point NAN_p(J_NAN, J_NAN);
612

613 614
               if(std::isnan(intersectionPoint._x) || std::isnan(intersectionPoint._y))
                    continue;
615

616 617 618 619 620
               Wall NewWall(intersectionPoint, bigWall.GetPoint2());// [IP -- P2]
               Wall NewWall2(bigWall.GetPoint1(), intersectionPoint);// [IP -- P2]

               WallPieces.push_back(NewWall);
               WallPieces.push_back(NewWall2);
621
#if DEBUG
622
               std::cout << "Add newwall: " << std::endl;
623 624
               NewWall.WriteToErrorLog();
               NewWall2.WriteToErrorLog();
625
#endif
626 627
          }
     }//other walls
628
#if DEBUG
629
     std::cout << "size " << WallPieces.size() << "\n";
630
     std::cout << "Leave collect\n--------" << std::endl;
631
#endif
632 633
// getc(stdin);

634 635 636 637
     return WallPieces;
}
bool Building::ReplaceBigWall(const std::shared_ptr<SubRoom>& subroom, const Wall& bigWall, std::vector<Wall>& WallPieces) const
{
Mohcine Chraibi's avatar
Mohcine Chraibi committed
638
#if DEBUG
639 640 641 642
     Log->Write("INFO Replacing big line in Room %d | Subroom %d with:", subroom->GetRoomID(), subroom->GetSubRoomID());
     bigWall.WriteToErrorLog();

     // REMOVE BigLINE
Mohcine Chraibi's avatar
Mohcine Chraibi committed
643

644
     std::cout << "\ns+ =" << subroom->GetAllWalls().size() << "\n";
645
#endif
Mohcine Chraibi's avatar
Mohcine Chraibi committed
646

647
     bool res = subroom->RemoveWall(bigWall);
Mohcine Chraibi's avatar
Mohcine Chraibi committed
648

649
#if DEBUG
650
     std::cout << "s- =" << subroom->GetAllWalls().size() << "\n";
651
#endif
652 653 654 655
     if(!res) {
          Log->Write("ERROR:  Correct fails. Could not remove wall: ");
          bigWall.WriteToErrorLog();
          return false;
656
     }
657
     // ADD SOME LINE
658 659 660 661 662 663
     res = AddWallToSubroom(subroom, WallPieces);
     if(!res) {
          Log->Write("ERROR:  Correct fails. Could not add new wall piece");
          return false;
     }

664
     return true;
665
}
666 667
const string& Building::GetProjectFilename() const
{
GrgrLmml's avatar
GrgrLmml committed
668
     return _configuration->GetProjectFile();
669 670
}

671 672
const string& Building::GetProjectRootDir() const
{
GrgrLmml's avatar
GrgrLmml committed
673
     return _configuration->GetProjectRootDir();
674
}
675

676 677
const std::string& Building::GetGeometryFilename() const
{
GrgrLmml's avatar
GrgrLmml committed
678
     return _configuration->GetGeometryFile();
679
}
680

681 682 683 684 685
bool Building::AddWallToSubroom(
        const std::shared_ptr<SubRoom> & subroom,
        std::vector<Wall> WallPieces) const
{ // CHOOSE WHICH PIECE SHOULD BE ADDED TO SUBROOM
// this is a challngig function
686
#if DEBUG
687 688 689
     std::cout << "\n-----\nEnter add_wall with:\n";
     for(const auto & w : WallPieces)
          w.WriteToErrorLog();
690
#endif
691
     auto walls = subroom->GetAllWalls();
692 693
     int maxCount = -1;
     Wall choosenWall;
694 695 696 697 698 699 700
     for(const auto & w : WallPieces) {
          // std::cout <<"\n check wall: \n";
          // w.WriteToErrorLog();
          int count = 0;
          for (const auto & checkWall: walls) {
               if (checkWall==w) continue;// don't count big wall
               if (w.ShareCommonPointWith(checkWall)) count++;
701 702 703 704 705 706 707 708 709 710
               else
               {   // first use the cheap ShareCommonPointWith() before entering
                   // this else
                    Point interP;
                    if (w.IntersectionWith(checkWall, interP))
                    {
                         if( (!std::isnan(interP._x)) && (!std::isnan(interP._y)))
                              count++;
                    }
               }
711 712 713 714 715 716 717 718 719
          }
          auto transitions = subroom->GetAllTransitions();
          auto crossings = subroom->GetAllCrossings();
          //auto h = subroom.second->GetAllHlines();
          for (auto transition: transitions)
               if (w.ShareCommonPointWith(*transition)) count++;
          for (auto crossing: crossings)
               if (w.ShareCommonPointWith(*crossing)) count++;

720 721
          if (count>=2)
          {
722
               subroom->AddWall(w);
723 724
#if DEBUG
               Log->Write("INFO: Wall candidate: ");
725
               w.WriteToErrorLog();
726 727 728 729 730 731 732 733 734
#endif
               if (count > maxCount)
               {
                    maxCount = count;
                    choosenWall = w;
               }
#if DEBUG
               std::cout << "\n -- count= " << count << ",  maxCount= " << maxCount << "\n";
#endif
735 736
          }
     }// WallPieces
737 738 739 740 741 742 743 744 745 746 747
     if(maxCount<0)
          return false;
     else
     {
#if DEBUG
          std::cout << KGRN << "Choosen Wall: " << RESET << std::endl;
          choosenWall.WriteToErrorLog();
#endif
          subroom->AddWall(choosenWall);
          return true;
     }
748 749
}

750 751 752
void Building::WriteToErrorLog() const
{
     Log->Write("GEOMETRY: ");
GrgrLmml's avatar
GrgrLmml committed
753
     for (int i = 0; i<GetNumberOfRooms(); i++) {
754 755 756 757 758 759
          Room* r = GetRoom(i);
          r->WriteToErrorLog();
     }
     Log->Write("ROUTING: ");

     for (map<int, Crossing*>::const_iterator iter = _crossings.begin();
GrgrLmml's avatar
GrgrLmml committed
760
          iter!=_crossings.end(); ++iter) {
761 762 763
          iter->second->WriteToErrorLog();
     }
     for (map<int, Transition*>::const_iterator iter = _transitions.begin();
GrgrLmml's avatar
GrgrLmml committed
764
          iter!=_transitions.end(); ++iter) {
765 766 767
          iter->second->WriteToErrorLog();
     }
     for (map<int, Hline*>::const_iterator iter = _hLines.begin();
GrgrLmml's avatar
GrgrLmml committed
768
          iter!=_hLines.end(); ++iter) {
769 770 771
          iter->second->WriteToErrorLog();
     }
     Log->Write("\n");
772 773
}

774 775
Room* Building::GetRoom(string caption) const
{
GrgrLmml's avatar
GrgrLmml committed
776 777
     for (const auto& it: _rooms) {
          if (it.second->GetCaption()==caption)
778
               return it.second.get();
779
     }
GrgrLmml's avatar
GrgrLmml committed
780
     Log->Write("ERROR: Room not found with caption "+caption);
781 782
     //return NULL;
     exit(EXIT_FAILURE);
783 784
}

785
bool Building::AddCrossing(Crossing* line)
786
{
787 788 789 790 791 792 793 794 795 796 797 798 799
	 int IDRoom = line->GetRoom1()->GetID();
	 int IDLine = line->GetID();
	 int IDCrossing = 1000 * IDRoom + IDLine;
	 if (_crossings.count(IDCrossing) != 0)
	 {
		 char tmp[CLENGTH];
		 sprintf(tmp,
			 "ERROR: Duplicate index for crossing found [%d] in Routing::AddCrossing()",
			 IDCrossing);
		 Log->Write(tmp);
		 exit(EXIT_FAILURE);
	 }
     _crossings[IDCrossing] = line;
800
     return true;
801 802
}

803
bool Building::AddTransition(Transition* line)
804
{
GrgrLmml's avatar
GrgrLmml committed
805
     if (_transitions.count(line->GetID())!=0) {
806 807
          char tmp[CLENGTH];
          sprintf(tmp,
808 809
                    "ERROR: Duplicate index for transition found [%d] in Routing::AddTransition()",
                    line->GetID());
810 811 812 813
          Log->Write(tmp);
          exit(EXIT_FAILURE);
     }
     _transitions[line->GetID()] = line;
814
     return true;
815 816
}

817
bool Building::AddHline(Hline* line)
818
{
GrgrLmml's avatar
GrgrLmml committed
819
     if (_hLines.count(line->GetID())!=0) {
820
          // check if the lines are identical
GrgrLmml's avatar
GrgrLmml committed
821 822 823
          Hline* ori = _hLines[line->GetID()];
          if (ori->operator==(*line)) {
               Log->Write("INFO: \tSkipping identical hlines with ID [%d]", line->GetID());
824
               return false;
GrgrLmml's avatar
GrgrLmml committed
825 826
          }
          else {
827
               Log->Write(
828 829
                         "ERROR: Duplicate index for hlines found [%d] in Routing::AddHline(). You have [%d] hlines",
                         line->GetID(), _hLines.size());
830 831 832 833
               exit(EXIT_FAILURE);
          }
     }
     _hLines[line->GetID()] = line;
834
     return true;
835 836
}

837
bool Building::AddGoal(Goal* goal)
838
{
GrgrLmml's avatar
GrgrLmml committed
839
     if (_goals.count(goal->GetId())!=0) {
840
          Log->Write(
841 842
                    "ERROR: Duplicate index for goal found [%d] in Routing::AddGoal()",
                    goal->GetId());
843 844 845
          exit(EXIT_FAILURE);
     }
     _goals[goal->GetId()] = goal;
846
     return true;
847 848
}

849 850 851
const map<int, Crossing*>& Building::GetAllCrossings() const
{
     return _crossings;
852 853
}

854 855 856
const map<int, Transition*>& Building::GetAllTransitions() const
{
     return _transitions;
857 858
}

859 860 861
const map<int, Hline*>& Building::GetAllHlines() const
{
     return _hLines;
862 863
}

864 865 866
const map<int, Goal*>& Building::GetAllGoals() const
{
     return _goals;
867 868
}

869 870 871 872
Transition* Building::GetTransition(string caption) const
{
     //eventually
     map<int, Transition*>::const_iterator itr;
GrgrLmml's avatar
GrgrLmml committed
873 874
     for (itr = _transitions.begin(); itr!=_transitions.end(); ++itr) {
          if (itr->second->GetCaption()==caption)
875 876 877
               return itr->second;
     }

GrgrLmml's avatar
GrgrLmml committed
878
     Log->Write("WARNING: No Transition with Caption: "+caption);
879
     exit(EXIT_FAILURE);
880 881
}

882
Transition* Building::GetTransition(int ID) const //ar.graf: added const 2015-12-10
883
{
GrgrLmml's avatar
GrgrLmml committed
884
     if (_transitions.count(ID)==1) {