diff --git a/CMakeLists.txt b/CMakeLists.txt index 4fdc6e3769c0296156dbd2e59676556a9b9e2bd8..c0d6bb1eb5f69401b6ca4d8693c420dd58fab115 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,36 +77,41 @@ if(DOXYGEN_FOUND) ) endif(DOXYGEN_FOUND) -#find the correct OpenMP flag +# find the correct OpenMP flag FIND_PACKAGE(OpenMP) if(OPENMP_FOUND) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") else(OPENMP_FOUND) - message( STATUS "Disabling OpenMP support" ) + if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp") + # somehow find_package(openmp) does not work properly with clang + else(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + message( STATUS "Disabling OpenMP support" ) + endif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") endif(OPENMP_FOUND) -#find and add the CGAL library +# find and add the CGAL library #fixme: complete this section -FIND_PACKAGE(CGAL QUIET) -if(CGAL_FOUND) - include (${CGAL_USE_FILE}) - INCLUDE_DIRECTORIES(${CGAL_CORE_INCLUDE_DIR}) - add_definitions(-D_CGAL=1) - message (SEND_ERROR "${CGAL_FOUND}") - message (FATAL_ERROR "${CGAL_CORE_INCLUDE_DIR}") - message (SEND_ERROR " Erreur: ${CGAL_FOUND}") - message (SEND_ERROR " Erreur: ${CGAL_USE_FILE}") -else(CGAL_FOUND) - message( STATUS "CGAL not found. But don't panik .." ) -endif(CGAL_FOUND) - -# test files: all cpp-files in Utest +# FIND_PACKAGE(CGAL QUIET) +# if(CGAL_FOUND) +# include (${CGAL_USE_FILE}) +# INCLUDE_DIRECTORIES(${CGAL_CORE_INCLUDE_DIR}) +# add_definitions(-D_CGAL=1) +# message (STATUS "${CGAL_FOUND}") +# message (STATUS "${CGAL_CORE_INCLUDE_DIR}") +# message (STATUS " Erreur: ${CGAL_FOUND}") +# message (STATUS " Erreur: ${CGAL_USE_FILE}") +# else(CGAL_FOUND) +# message( STATUS "CGAL not found." ) +# endif(CGAL_FOUND) + +# test all cpp-files in Utest if(BUILD_TESTING) file(GLOB test_files "${CMAKE_TEST_DIR}/*.cpp") endif(BUILD_TESTING) - +# add sources and headers set ( source_files main.cpp Simulation.cpp @@ -275,30 +280,43 @@ if(CGAL_FOUND) target_link_libraries (jpscore ${CGAL_CORE_LIBRARY}) endif(CGAL_FOUND) #---------------------------- compiler ------------------------------- +# Initialize CXXFLAGS. +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g -Wunused-variable -Wunused-parameter -Wunused-function -Wunused") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -DNDEBUG") +# check c++-11 +if((CMAKE_COMPILER_IS_GNUCXX AND NOT ${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 4.6) OR + (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT ${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 3.1)) + message(STATUS "Checking for C++11 compiler - available") +else() + message(STATUS "Checking for C++11 compiler - unavailable") +endif() +# c++-11 flags +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") +endif() + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - message(STATUS "Using CLANG++" ) + message(STATUS "Using Clang" ) endif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") if(CMAKE_COMPILER_IS_GNUCXX) - message( STATUS "Set compiler flags (g++)" ) - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall -std=c++11") + message( STATUS "Using g++" ) endif(CMAKE_COMPILER_IS_GNUCXX) -if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_BUILD_TYPE MATCHES Debug) +if(CMAKE_BUILD_TYPE MATCHES Debug) message(STATUS "In Debug Build") - set(WITH_COVERAGE TRUE) - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -W -Wshadow -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wno-system-headers -Wno-deprecated -Woverloaded-virtual -Wwrite-strings -fprofile-arcs -ftest-coverage -std=c++11") set(CMAKE_CXX_LDFLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage") - message(STATUS "Debug flags for coverage: " ${CMAKE_CXX_FLAGS_DEBUG} ) -else(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_BUILD_TYPE MATCHES Debug) - message(STATUS "Release flags: " ${CMAKE_CXX_FLAGS_RELEASE} ) -endif(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_BUILD_TYPE MATCHES Debug) + message(STATUS "Debug flags: " ${CMAKE_CXX_FLAGS} " " ${CMAKE_CXX_FLAGS_DEBUG} ) +else(CMAKE_BUILD_TYPE MATCHES Debug) + message(STATUS "Release flags: " ${CMAKE_CXX_FLAGS} " " ${CMAKE_CXX_FLAGS_RELEASE} ) + endif(CMAKE_BUILD_TYPE MATCHES Debug) # ----------------------------- cTest ------------------------------------------ if(BUILD_TESTING) - enable_testing() #adds another build target, which is test for Makefile generators - include(CTest) #adding Dart support + enable_testing() # adds another build target, which is test for Makefile generators + include(CTest) # adding Dart support - #test if code compiles and runs default setting. Takes about 30 seconds + # test if code compiles and runs default setting. Takes about 30 seconds add_test (jpscore_compile ${CMAKE_CTEST_COMMAND} --build-and-test "${CMAKE_SOURCE_DIR}" "${EXECUTABLE_OUTPUT_PATH}" #"${CMAKE_BINARY_DIR}" --build-generator ${CMAKE_GENERATOR} diff --git a/IO/IODispatcher.cpp b/IO/IODispatcher.cpp index bda6af9deaddf9225808d1051ba5a22324019639..ccd2c70f3ab0dcb1ad2321ca074c7aceee2303c8 100644 --- a/IO/IODispatcher.cpp +++ b/IO/IODispatcher.cpp @@ -36,264 +36,274 @@ using namespace std; -IODispatcher::IODispatcher() { - pHandlers = vector<OutputHandler*>(); +IODispatcher::IODispatcher() +{ + pHandlers = vector<OutputHandler*>(); } -IODispatcher::~IODispatcher() { - for (int i = 0; i < (int) pHandlers.size(); i++) - delete pHandlers[i]; - pHandlers.clear(); +IODispatcher::~IODispatcher() +{ + for (int i = 0; i < (int) pHandlers.size(); i++) + delete pHandlers[i]; + pHandlers.clear(); } -void IODispatcher::AddIO(OutputHandler* ioh) { - pHandlers.push_back(ioh); +void IODispatcher::AddIO(OutputHandler* ioh) +{ + pHandlers.push_back(ioh); } -const vector<OutputHandler*>& IODispatcher::GetIOHandlers() { - return pHandlers; +const vector<OutputHandler*>& IODispatcher::GetIOHandlers() +{ + return pHandlers; } -void IODispatcher::Write(const std::string& str) { - for (vector<OutputHandler*>::iterator it = pHandlers.begin(); - it != pHandlers.end(); ++it) { - (*it)->Write(str); - } +void IODispatcher::Write(const std::string& str) +{ + for (vector<OutputHandler*>::iterator it = pHandlers.begin(); + it != pHandlers.end(); ++it) { + (*it)->Write(str); + } } -string IODispatcher::WritePed(Pedestrian* ped) { - double RAD2DEG = 180.0 / M_PI; - char tmp[CLENGTH] = ""; - - double v0 = ped->GetV0Norm(); - if (v0 == 0.0) { - Log->Write("ERROR: IODispatcher::WritePed()\t v0=0"); - exit(0); - } - double v = ped->GetV().Norm(); - int color = (int) (v / v0 * 255); - if(ped->GetSpotlight()==false) color=-1; - - double a = ped->GetLargerAxis(); - double b = ped->GetSmallerAxis(); - double phi = atan2(ped->GetEllipse().GetSinPhi(), ped->GetEllipse().GetCosPhi()); - sprintf(tmp, "<agent ID=\"%d\"\t" - "xPos=\"%.2f\"\tyPos=\"%.2f\"\t" - "zPos=\"%.2f\"\t" - "radiusA=\"%.2f\"\tradiusB=\"%.2f\"\t" - "ellipseOrientation=\"%.2f\" ellipseColor=\"%d\"/>\n", - ped->GetID(), (ped->GetPos().GetX()) * FAKTOR, - (ped->GetPos().GetY()) * FAKTOR,(ped->GetElevation()+0.3) * FAKTOR ,a * FAKTOR, b * FAKTOR, - phi * RAD2DEG, color); - return tmp; +string IODispatcher::WritePed(Pedestrian* ped) +{ + double RAD2DEG = 180.0 / M_PI; + char tmp[CLENGTH] = ""; + + double v0 = ped->GetV0Norm(); + if (v0 == 0.0) { + Log->Write("ERROR: IODispatcher::WritePed()\t v0=0"); + exit(0); + } + double v = ped->GetV().Norm(); + int color = (int) (v / v0 * 255); + if(ped->GetSpotlight()==false) color=-1; + + double a = ped->GetLargerAxis(); + double b = ped->GetSmallerAxis(); + double phi = atan2(ped->GetEllipse().GetSinPhi(), ped->GetEllipse().GetCosPhi()); + sprintf(tmp, "<agent ID=\"%d\"\t" + "xPos=\"%.2f\"\tyPos=\"%.2f\"\t" + "zPos=\"%.2f\"\t" + "radiusA=\"%.2f\"\tradiusB=\"%.2f\"\t" + "ellipseOrientation=\"%.2f\" ellipseColor=\"%d\"/>\n", + ped->GetID(), (ped->GetPos().GetX()) * FAKTOR, + (ped->GetPos().GetY()) * FAKTOR,(ped->GetElevation()+0.3) * FAKTOR ,a * FAKTOR, b * FAKTOR, + phi * RAD2DEG, color); + return tmp; } -void IODispatcher::WriteHeader(int nPeds, double fps, Building* building, int seed ) { - - nPeds = building->GetNumberOfPedestrians(); - string tmp; - tmp = - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n" "<trajectories>\n"; - char agents[CLENGTH] = ""; - sprintf(agents, "\t<header version = \"%s\">\n", JPS_VERSION); - tmp.append(agents); - sprintf(agents, "\t\t<agents>%d</agents>\n", nPeds); - tmp.append(agents); - sprintf(agents, "\t\t<seed>%d</seed>\n", seed); - tmp.append(agents); - sprintf(agents, "\t\t<frameRate>%f</frameRate>\n", fps); - tmp.append(agents); - tmp.append("\t</header>\n"); - Write(tmp); +void IODispatcher::WriteHeader(int nPeds, double fps, Building* building, int seed ) +{ + + nPeds = building->GetNumberOfPedestrians(); + string tmp; + tmp = + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n" "<trajectories>\n"; + char agents[CLENGTH] = ""; + sprintf(agents, "\t<header version = \"%s\">\n", JPS_VERSION); + tmp.append(agents); + sprintf(agents, "\t\t<agents>%d</agents>\n", nPeds); + tmp.append(agents); + sprintf(agents, "\t\t<seed>%d</seed>\n", seed); + tmp.append(agents); + sprintf(agents, "\t\t<frameRate>%f</frameRate>\n", fps); + tmp.append(agents); + tmp.append("\t</header>\n"); + Write(tmp); } -void IODispatcher::WriteGeometry(Building* building) { - // just put a link to the geometry file - string embed_geometry; - embed_geometry.append("\t<geometry>\n"); - char file_location[CLENGTH] = ""; - sprintf(file_location, "\t<file location= \"%s\"/>\n", building->GetGeometryFilename().c_str()); - embed_geometry.append(file_location); - embed_geometry.append("\t</geometry>\n"); - //Write(embed_geometry); - //return; - // - string geometry; - geometry.append("\t<geometry>\n"); - - bool plotHlines = true; - bool plotCrossings = true; - bool plotTransitions = true; - bool plotPlayingField=false; - vector<string> rooms_to_plot; - - //Promenade - //rooms_to_plot.push_back("outside"); - //rooms_to_plot.push_back("010"); - - // first the rooms - //to avoid writing navigation line twice - vector<int> navLineWritten; - - for (int i = 0; i < building->GetNumberOfRooms(); i++) { - Room* r = building->GetRoom(i); - string caption = r->GetCaption(); //if(r->GetID()!=1) continue; - if (rooms_to_plot.empty() == false) - if (IsElementInVector(rooms_to_plot, caption) == false) - continue; - - for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { - SubRoom* s = r->GetSubRoom(k); //if(s->GetSubRoomID()!=0) continue; - geometry.append(s->WriteSubRoom()); - - // the hlines - if (plotHlines) { - const vector<Hline*>& hlines = s->GetAllHlines(); - for (unsigned int i = 0; i < hlines.size(); i++) { - Hline* hline = hlines[i]; - int uid1 = hline->GetUniqueID(); - if (!IsElementInVector(navLineWritten, uid1)) { - navLineWritten.push_back(uid1); - if (rooms_to_plot.empty() - || IsElementInVector(rooms_to_plot, caption)) { - geometry.append(hline->WriteElement()); - } +void IODispatcher::WriteGeometry(Building* building) +{ + // just put a link to the geometry file + string embed_geometry; + embed_geometry.append("\t<geometry>\n"); + char file_location[CLENGTH] = ""; + sprintf(file_location, "\t<file location= \"%s\"/>\n", building->GetGeometryFilename().c_str()); + embed_geometry.append(file_location); + embed_geometry.append("\t</geometry>\n"); + //Write(embed_geometry); + //return; + // + string geometry; + geometry.append("\t<geometry>\n"); + + bool plotHlines = true; + bool plotCrossings = true; + bool plotTransitions = true; + bool plotPlayingField=false; + vector<string> rooms_to_plot; + + //Promenade + //rooms_to_plot.push_back("outside"); + //rooms_to_plot.push_back("010"); + + // first the rooms + //to avoid writing navigation line twice + vector<int> navLineWritten; + + for (int i = 0; i < building->GetNumberOfRooms(); i++) { + Room* r = building->GetRoom(i); + string caption = r->GetCaption(); //if(r->GetID()!=1) continue; + if (rooms_to_plot.empty() == false) + if (IsElementInVector(rooms_to_plot, caption) == false) + continue; + + for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { + SubRoom* s = r->GetSubRoom(k); //if(s->GetSubRoomID()!=0) continue; + geometry.append(s->WriteSubRoom()); + + // the hlines + if (plotHlines) { + const vector<Hline*>& hlines = s->GetAllHlines(); + for (unsigned int i = 0; i < hlines.size(); i++) { + Hline* hline = hlines[i]; + int uid1 = hline->GetUniqueID(); + if (!IsElementInVector(navLineWritten, uid1)) { + navLineWritten.push_back(uid1); + if (rooms_to_plot.empty() + || IsElementInVector(rooms_to_plot, caption)) { + geometry.append(hline->WriteElement()); + } + } + } + + // the crossings + if (plotCrossings) { + const vector<Crossing*>& crossings = s->GetAllCrossings(); + for (unsigned int i = 0; i < crossings.size(); i++) { + Crossing* crossing = crossings[i]; + int uid1 = crossing->GetUniqueID(); + if (!IsElementInVector(navLineWritten, uid1)) { + navLineWritten.push_back(uid1); + if (rooms_to_plot.empty() + || IsElementInVector(rooms_to_plot, + caption)) { + geometry.append(crossing->WriteElement()); + } + } + } + } + + // the transitions + if (plotTransitions) { + const vector<Transition*>& transitions = + s->GetAllTransitions(); + for (unsigned int i = 0; i < transitions.size(); i++) { + Transition* transition = transitions[i]; + int uid1 = transition->GetUniqueID(); + if (!IsElementInVector(navLineWritten, uid1)) { + navLineWritten.push_back(uid1); + + if (rooms_to_plot.empty()) { + geometry.append(transition->WriteElement()); + + } else { + + Room* room1 = transition->GetRoom1(); + Room* room2 = transition->GetRoom2(); + string caption1 = room1->GetCaption(); + if (room2) { + string caption2 = room2->GetCaption(); + if (IsElementInVector(rooms_to_plot, + caption1) + || IsElementInVector(rooms_to_plot, + caption2)) { + geometry.append(transition->WriteElement()); + } + + } else { + if (IsElementInVector(rooms_to_plot, + caption1)) { + geometry.append(transition->WriteElement()); + } } - } - - // the crossings - if (plotCrossings) { - const vector<Crossing*>& crossings = s->GetAllCrossings(); - for (unsigned int i = 0; i < crossings.size(); i++) { - Crossing* crossing = crossings[i]; - int uid1 = crossing->GetUniqueID(); - if (!IsElementInVector(navLineWritten, uid1)) { - navLineWritten.push_back(uid1); - if (rooms_to_plot.empty() - || IsElementInVector(rooms_to_plot, - caption)) { - geometry.append(crossing->WriteElement()); - } - } - } - } - - // the transitions - if (plotTransitions) { - const vector<Transition*>& transitions = - s->GetAllTransitions(); - for (unsigned int i = 0; i < transitions.size(); i++) { - Transition* transition = transitions[i]; - int uid1 = transition->GetUniqueID(); - if (!IsElementInVector(navLineWritten, uid1)) { - navLineWritten.push_back(uid1); - - if (rooms_to_plot.empty()) { - geometry.append(transition->WriteElement()); - - } else { - - Room* room1 = transition->GetRoom1(); - Room* room2 = transition->GetRoom2(); - string caption1 = room1->GetCaption(); - if (room2) { - string caption2 = room2->GetCaption(); - if (IsElementInVector(rooms_to_plot, - caption1) - || IsElementInVector(rooms_to_plot, - caption2)) { - geometry.append(transition->WriteElement()); - } - - } else { - if (IsElementInVector(rooms_to_plot, - caption1)) { - geometry.append(transition->WriteElement()); - } - } - - } - } - } - } - } - } - } - - //eventually write any goal - for (map<int, Goal*>::const_iterator itr = building->GetAllGoals().begin(); - itr != building->GetAllGoals().end(); ++itr) { - geometry.append(itr->second->Write()); - } - - if(plotPlayingField){ - //add the playing area - double width=3282; - double length=5668; - char tmp[100]; - geometry.append("\t\t<wall>\n"); - sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n",-length,width); - geometry.append(tmp); - - sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n",-length,-width); - geometry.append(tmp); - sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n",length,-width); - geometry.append(tmp); - sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n",length,width); - geometry.append(tmp); - sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n",-length,width); - geometry.append(tmp); - geometry.append("\t\t</wall>\n"); - - geometry.append("\t\t<wall>\n"); - sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n",0.0,width); - geometry.append(tmp); - sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n",0.0,-width); - geometry.append(tmp); - geometry.append("\t\t</wall>\n"); - } - geometry.append("\t</geometry>\n"); - Write(geometry); + + } + } + } + } + } + } + } + + //eventually write any goal + for (map<int, Goal*>::const_iterator itr = building->GetAllGoals().begin(); + itr != building->GetAllGoals().end(); ++itr) { + geometry.append(itr->second->Write()); + } + + if(plotPlayingField) { + //add the playing area + double width=3282; + double length=5668; + char tmp[100]; + geometry.append("\t\t<wall>\n"); + sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n",-length,width); + geometry.append(tmp); + + sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n",-length,-width); + geometry.append(tmp); + sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n",length,-width); + geometry.append(tmp); + sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n",length,width); + geometry.append(tmp); + sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n",-length,width); + geometry.append(tmp); + geometry.append("\t\t</wall>\n"); + + geometry.append("\t\t<wall>\n"); + sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n",0.0,width); + geometry.append(tmp); + sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n",0.0,-width); + geometry.append(tmp); + geometry.append("\t\t</wall>\n"); + } + geometry.append("\t</geometry>\n"); + Write(geometry); } -void IODispatcher::WriteFrame(int frameNr, Building* building) { - string data; - char tmp[CLENGTH] = ""; - vector<string> rooms_to_plot; - - //promenade - //rooms_to_plot.push_back("010"); - - sprintf(tmp, "<frame ID=\"%d\">\n", frameNr); - data.append(tmp); - - for (int roomindex = 0; roomindex < building->GetNumberOfRooms(); roomindex++) { - Room* r = building->GetRoom(roomindex); - string caption = r->GetCaption(); - - if ((rooms_to_plot.empty() == false) - && (IsElementInVector(rooms_to_plot, caption) == false)) { - continue; - } - - for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { - SubRoom* s = r->GetSubRoom(k); - for (int i = 0; i < s->GetNumberOfPedestrians(); ++i) { - Pedestrian* ped = s->GetPedestrian(i); - data.append(WritePed(ped)); - } - } - } - data.append("</frame>\n"); - Write(data); +void IODispatcher::WriteFrame(int frameNr, Building* building) +{ + string data; + char tmp[CLENGTH] = ""; + vector<string> rooms_to_plot; + + //promenade + //rooms_to_plot.push_back("010"); + + sprintf(tmp, "<frame ID=\"%d\">\n", frameNr); + data.append(tmp); + + for (int roomindex = 0; roomindex < building->GetNumberOfRooms(); roomindex++) { + Room* r = building->GetRoom(roomindex); + string caption = r->GetCaption(); + + if ((rooms_to_plot.empty() == false) + && (IsElementInVector(rooms_to_plot, caption) == false)) { + continue; + } + + for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { + SubRoom* s = r->GetSubRoom(k); + for (int i = 0; i < s->GetNumberOfPedestrians(); ++i) { + Pedestrian* ped = s->GetPedestrian(i); + data.append(WritePed(ped)); + } + } + } + data.append("</frame>\n"); + Write(data); } -void IODispatcher::WriteFooter() { - Write("</trajectories>\n"); +void IODispatcher::WriteFooter() +{ + Write("</trajectories>\n"); } @@ -302,37 +312,42 @@ void IODispatcher::WriteFooter() { */ TrajectoriesFLAT::TrajectoriesFLAT() : - IODispatcher() { + IODispatcher() +{ } -void TrajectoriesFLAT::WriteHeader(int nPeds, double fps, Building* building, int seed) { +void TrajectoriesFLAT::WriteHeader(int nPeds, double fps, Building* building, int seed) +{ } -void TrajectoriesFLAT::WriteGeometry(Building* building) { +void TrajectoriesFLAT::WriteGeometry(Building* building) +{ } -void TrajectoriesFLAT::WriteFrame(int frameNr, Building* building) { - char tmp[CLENGTH] = ""; - - for (int roomindex = 0; roomindex < building->GetNumberOfRooms(); roomindex++) { - Room* r = building->GetRoom(roomindex); - for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { - SubRoom* s = r->GetSubRoom(k); - for (int i = 0; i < s->GetNumberOfPedestrians(); ++i) { - Pedestrian* ped = s->GetPedestrian(i); - double x = ped->GetPos().GetX(); - double y = ped->GetPos().GetY(); - sprintf(tmp, "%d\t%d\t%f\t%f", ped->GetID(), frameNr, x, - y); - Write(tmp); - } - } - } +void TrajectoriesFLAT::WriteFrame(int frameNr, Building* building) +{ + char tmp[CLENGTH] = ""; + + for (int roomindex = 0; roomindex < building->GetNumberOfRooms(); roomindex++) { + Room* r = building->GetRoom(roomindex); + for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { + SubRoom* s = r->GetSubRoom(k); + for (int i = 0; i < s->GetNumberOfPedestrians(); ++i) { + Pedestrian* ped = s->GetPedestrian(i); + double x = ped->GetPos().GetX(); + double y = ped->GetPos().GetY(); + sprintf(tmp, "%d\t%d\t%f\t%f", ped->GetID(), frameNr, x, + y); + Write(tmp); + } + } + } } -void TrajectoriesFLAT::WriteFooter() { +void TrajectoriesFLAT::WriteFooter() +{ } @@ -342,66 +357,71 @@ void TrajectoriesFLAT::WriteFooter() { */ -TrajectoriesVTK::TrajectoriesVTK() { +TrajectoriesVTK::TrajectoriesVTK() +{ } -void TrajectoriesVTK::WriteHeader(int nPeds, double fps, Building* building, int seed) { - Write("# vtk DataFile Version 4.0"); - Write(building->GetCaption()); - Write("ASCII"); - Write(""); +void TrajectoriesVTK::WriteHeader(int nPeds, double fps, Building* building, int seed) +{ + Write("# vtk DataFile Version 4.0"); + Write(building->GetCaption()); + Write("ASCII"); + Write(""); } -void TrajectoriesVTK::WriteGeometry(Building* building) { - stringstream tmp; - - NavMesh* nv= new NavMesh(building); - nv->BuildNavMesh(); - //nv->WriteToFile("../pedunc/examples/stadium/arena.nav"); - Write("DATASET UNSTRUCTURED_GRID"); - - //writing the vertices - const vector<NavMesh::JVertex*>& vertices= nv->GetVertices() ; - tmp<<"POINTS "<<vertices.size()<<" FLOAT"<<endl; - for (unsigned int v=0;v<vertices.size();v++){ - tmp<<vertices[v]->pPos.GetX()<<" " <<vertices[v]->pPos.GetY() <<" 0.0"<<endl; - } - Write(tmp.str()); - tmp.str(std::string()); - - //writing the cells data - const vector<NavMesh::JNode*>& cells= nv->GetNodes(); - int nComponents=cells.size(); - stringstream tmp1; - for (unsigned int n=0;n<cells.size();n++){ - int hSize=cells[n]->pHull.size(); - - tmp1<<hSize<<""; - for(unsigned int i=0;i<cells[n]->pHull.size();i++){ - tmp1<<" "<<cells[n]->pHull[i].id; - } - tmp1<<endl; - nComponents+= hSize; - } - tmp<<"CELLS "<<cells.size()<<" "<<nComponents<<endl; - tmp<<tmp1.str(); - Write(tmp.str()); - tmp.str(std::string()); - - // writing the cell type - tmp<<"CELL_TYPES "<<cells.size()<<endl; - for (unsigned int n=0;n<cells.size();n++){ - tmp<<"9"<<endl; - } - - Write(tmp.str()); - delete nv; +void TrajectoriesVTK::WriteGeometry(Building* building) +{ + stringstream tmp; + + NavMesh* nv= new NavMesh(building); + nv->BuildNavMesh(); + //nv->WriteToFile("../pedunc/examples/stadium/arena.nav"); + Write("DATASET UNSTRUCTURED_GRID"); + + //writing the vertices + const vector<NavMesh::JVertex*>& vertices= nv->GetVertices() ; + tmp<<"POINTS "<<vertices.size()<<" FLOAT"<<endl; + for (unsigned int v=0; v<vertices.size(); v++) { + tmp<<vertices[v]->pPos.GetX()<<" " <<vertices[v]->pPos.GetY() <<" 0.0"<<endl; + } + Write(tmp.str()); + tmp.str(std::string()); + + //writing the cells data + const vector<NavMesh::JNode*>& cells= nv->GetNodes(); + int nComponents=cells.size(); + stringstream tmp1; + for (unsigned int n=0; n<cells.size(); n++) { + int hSize=cells[n]->pHull.size(); + + tmp1<<hSize<<""; + for(unsigned int i=0; i<cells[n]->pHull.size(); i++) { + tmp1<<" "<<cells[n]->pHull[i].id; + } + tmp1<<endl; + nComponents+= hSize; + } + tmp<<"CELLS "<<cells.size()<<" "<<nComponents<<endl; + tmp<<tmp1.str(); + Write(tmp.str()); + tmp.str(std::string()); + + // writing the cell type + tmp<<"CELL_TYPES "<<cells.size()<<endl; + for (unsigned int n=0; n<cells.size(); n++) { + tmp<<"9"<<endl; + } + + Write(tmp.str()); + delete nv; } -void TrajectoriesVTK::WriteFrame(int frameNr, Building* building) { +void TrajectoriesVTK::WriteFrame(int frameNr, Building* building) +{ } -void TrajectoriesVTK::WriteFooter() { +void TrajectoriesVTK::WriteFooter() +{ } @@ -409,122 +429,127 @@ void TrajectoriesVTK::WriteFooter() { -void TrajectoriesJPSV06::WriteHeader(int nPeds, double fps, Building* building, int seed){ - nPeds = building->GetNumberOfPedestrians(); - string tmp; - tmp = - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n" "<trajectories>\n"; - char agents[CLENGTH] = ""; - sprintf(agents, "\t<header version = \"0.6\">\n"); - tmp.append(agents); - sprintf(agents, "\t\t<agents>%d</agents>\n", nPeds); - tmp.append(agents); - sprintf(agents, "\t\t<seed>%d</seed>\n", seed); - tmp.append(agents); - sprintf(agents, "\t\t<frameRate>%f</frameRate>\n", fps); - tmp.append(agents); - tmp.append("\t\t<!-- Frame count HACK\n"); - tmp.append("replace me\n"); - tmp.append("\t\tFrame count HACK -->\n"); +void TrajectoriesJPSV06::WriteHeader(int nPeds, double fps, Building* building, int seed) +{ + nPeds = building->GetNumberOfPedestrians(); + string tmp; + tmp = + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n" "<trajectories>\n"; + char agents[CLENGTH] = ""; + sprintf(agents, "\t<header version = \"0.6\">\n"); + tmp.append(agents); + sprintf(agents, "\t\t<agents>%d</agents>\n", nPeds); + tmp.append(agents); + sprintf(agents, "\t\t<seed>%d</seed>\n", seed); + tmp.append(agents); + sprintf(agents, "\t\t<frameRate>%f</frameRate>\n", fps); + tmp.append(agents); + tmp.append("\t\t<!-- Frame count HACK\n"); + tmp.append("replace me\n"); + tmp.append("\t\tFrame count HACK -->\n"); // tmp.append("<frameCount>xxxxxxx</frameCount>\n"); - tmp.append("\t</header>\n"); - Write(tmp); + tmp.append("\t</header>\n"); + Write(tmp); } -void TrajectoriesJPSV06::WriteGeometry(Building* building){ - // just put a link to the geometry file - string embed_geometry; - embed_geometry.append("\t<geometry>\n"); - char file_location[CLENGTH] = ""; - sprintf(file_location, "\t<file location= \"%s\"/>\n", building->GetGeometryFilename().c_str()); - embed_geometry.append(file_location); - embed_geometry.append("\t</geometry>\n"); - Write(embed_geometry); - - Write("\t<AttributeDescription>"); - Write("\t\t<property tag=\"x\" description=\"xPosition\"/>"); - Write("\t\t<property tag=\"y\" description=\"yPosition\"/>"); - Write("\t\t<property tag=\"z\" description=\"zPosition\"/>"); - Write("\t\t<property tag=\"rA\" description=\"radiusA\"/>"); - Write("\t\t<property tag=\"rB\" description=\"radiusB\"/>"); - Write("\t\t<property tag=\"eC\" description=\"ellipseColor\"/>"); - Write("\t\t<property tag=\"eO\" description=\"ellipseOrientation\"/>"); - Write("\t</AttributeDescription>\n"); +void TrajectoriesJPSV06::WriteGeometry(Building* building) +{ + // just put a link to the geometry file + string embed_geometry; + embed_geometry.append("\t<geometry>\n"); + char file_location[CLENGTH] = ""; + sprintf(file_location, "\t<file location= \"%s\"/>\n", building->GetGeometryFilename().c_str()); + embed_geometry.append(file_location); + embed_geometry.append("\t</geometry>\n"); + Write(embed_geometry); + + Write("\t<AttributeDescription>"); + Write("\t\t<property tag=\"x\" description=\"xPosition\"/>"); + Write("\t\t<property tag=\"y\" description=\"yPosition\"/>"); + Write("\t\t<property tag=\"z\" description=\"zPosition\"/>"); + Write("\t\t<property tag=\"rA\" description=\"radiusA\"/>"); + Write("\t\t<property tag=\"rB\" description=\"radiusB\"/>"); + Write("\t\t<property tag=\"eC\" description=\"ellipseColor\"/>"); + Write("\t\t<property tag=\"eO\" description=\"ellipseOrientation\"/>"); + Write("\t</AttributeDescription>\n"); } -void TrajectoriesJPSV06::WriteFrame(int frameNr, Building* building){ - string data; - char tmp[CLENGTH] = ""; - double RAD2DEG = 180.0 / M_PI; - vector<string> rooms_to_plot; - - //promenade - //rooms_to_plot.push_back("010"); - - sprintf(tmp, "<frame ID=\"%d\">\n", frameNr); - data.append(tmp); - - for (int roomindex = 0; roomindex < building->GetNumberOfRooms(); roomindex++) { - Room* r = building->GetRoom(roomindex); - string caption = r->GetCaption(); - - if ((rooms_to_plot.empty() == false) - && (IsElementInVector(rooms_to_plot, caption) == false)) { - continue; - } - - for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { - SubRoom* s = r->GetSubRoom(k); - for (int i = 0; i < s->GetNumberOfPedestrians(); ++i) { - Pedestrian* ped = s->GetPedestrian(i); - - - char tmp[CLENGTH] = ""; - - double v0 = ped->GetV0Norm(); - if (v0 == 0.0) { - Log->Write("ERROR: TrajectoriesJPSV06()\t v0=0"); - exit(0); - } - double v = ped->GetV().Norm(); - int color = (int) (v / v0 * 255); - if(ped->GetSpotlight()==false) color=-1; - - double a = ped->GetLargerAxis(); - double b = ped->GetSmallerAxis(); - double phi = atan2(ped->GetEllipse().GetSinPhi(), ped->GetEllipse().GetCosPhi()); - sprintf(tmp, "<agent ID=\"%d\"\t" - "x=\"%.2f\"\ty=\"%.2f\"\t" - "z=\"%.2f\"\t" - "rA=\"%.2f\"\trB=\"%.2f\"\t" - "eO=\"%.2f\" eC=\"%d\"/>\n", - ped->GetID(), (ped->GetPos().GetX()) * FAKTOR, - (ped->GetPos().GetY()) * FAKTOR,(ped->GetElevation()+0.3) * FAKTOR ,a * FAKTOR, b * FAKTOR, - phi * RAD2DEG, color); - data.append(tmp); - } - } - } - data.append("</frame>\n"); - Write(data); +void TrajectoriesJPSV06::WriteFrame(int frameNr, Building* building) +{ + string data; + char tmp[CLENGTH] = ""; + double RAD2DEG = 180.0 / M_PI; + vector<string> rooms_to_plot; + + //promenade + //rooms_to_plot.push_back("010"); + + sprintf(tmp, "<frame ID=\"%d\">\n", frameNr); + data.append(tmp); + + for (int roomindex = 0; roomindex < building->GetNumberOfRooms(); roomindex++) { + Room* r = building->GetRoom(roomindex); + string caption = r->GetCaption(); + + if ((rooms_to_plot.empty() == false) + && (IsElementInVector(rooms_to_plot, caption) == false)) { + continue; + } + + for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { + SubRoom* s = r->GetSubRoom(k); + for (int i = 0; i < s->GetNumberOfPedestrians(); ++i) { + Pedestrian* ped = s->GetPedestrian(i); + + + char tmp[CLENGTH] = ""; + + double v0 = ped->GetV0Norm(); + if (v0 == 0.0) { + Log->Write("ERROR: TrajectoriesJPSV06()\t v0=0"); + exit(0); + } + double v = ped->GetV().Norm(); + int color = (int) (v / v0 * 255); + if(ped->GetSpotlight()==false) color=-1; + + double a = ped->GetLargerAxis(); + double b = ped->GetSmallerAxis(); + double phi = atan2(ped->GetEllipse().GetSinPhi(), ped->GetEllipse().GetCosPhi()); + sprintf(tmp, "<agent ID=\"%d\"\t" + "x=\"%.2f\"\ty=\"%.2f\"\t" + "z=\"%.2f\"\t" + "rA=\"%.2f\"\trB=\"%.2f\"\t" + "eO=\"%.2f\" eC=\"%d\"/>\n", + ped->GetID(), (ped->GetPos().GetX()) * FAKTOR, + (ped->GetPos().GetY()) * FAKTOR,(ped->GetElevation()+0.3) * FAKTOR ,a * FAKTOR, b * FAKTOR, + phi * RAD2DEG, color); + data.append(tmp); + } + } + } + data.append("</frame>\n"); + Write(data); } -void TrajectoriesJPSV06::WriteFooter(){ - Write("</trajectories>\n"); +void TrajectoriesJPSV06::WriteFooter() +{ + Write("</trajectories>\n"); } -void TrajectoriesXML_MESH::WriteGeometry(Building* building){ - //Navigation mesh implementation - NavMesh* nv= new NavMesh(building); - nv->BuildNavMesh(); - string geometry; - nv->WriteToString(geometry); - Write("<geometry>"); - Write(geometry); - Write("</geometry>"); - nv->WriteToFile(building->GetProjectFilename()+".full.nav"); - delete nv; +void TrajectoriesXML_MESH::WriteGeometry(Building* building) +{ + //Navigation mesh implementation + NavMesh* nv= new NavMesh(building); + nv->BuildNavMesh(); + string geometry; + nv->WriteToString(geometry); + Write("<geometry>"); + Write(geometry); + Write("</geometry>"); + nv->WriteToFile(building->GetProjectFilename()+".full.nav"); + delete nv; } diff --git a/IO/IODispatcher.h b/IO/IODispatcher.h index 6fcfb4169638374581fe6d05a0ee37a274cd06a1..771e9038cb633b8396e2e2f94522e920b1bb12ed 100644 --- a/IO/IODispatcher.h +++ b/IO/IODispatcher.h @@ -38,35 +38,35 @@ extern OutputHandler* Log; class IODispatcher { - private: - std::vector<OutputHandler* > pHandlers; - std::string WritePed(Pedestrian* ped); - - public: - IODispatcher(); - IODispatcher(const IODispatcher& orig); - virtual ~IODispatcher(); - - void AddIO(OutputHandler* ioh); - const std::vector<OutputHandler*>& GetIOHandlers(); - void Write(const std::string& str); - virtual void WriteHeader(int nPeds, double fps, Building* building, int seed); - virtual void WriteGeometry(Building* building); - virtual void WriteFrame(int frameNr, Building* building); - virtual void WriteFooter(); - int AreaLevel(std::string caption); - - - template<typename A> - bool IsElementInVector(const std::vector<A> &vec, A& el) { - typename std::vector<A>::const_iterator it; - it = std::find (vec.begin(), vec.end(), el); - if(it==vec.end()){ - return false; - }else{ - return true; - } - } +private: + std::vector<OutputHandler* > pHandlers; + std::string WritePed(Pedestrian* ped); + +public: + IODispatcher(); + IODispatcher(const IODispatcher& orig); + virtual ~IODispatcher(); + + void AddIO(OutputHandler* ioh); + const std::vector<OutputHandler*>& GetIOHandlers(); + void Write(const std::string& str); + virtual void WriteHeader(int nPeds, double fps, Building* building, int seed); + virtual void WriteGeometry(Building* building); + virtual void WriteFrame(int frameNr, Building* building); + virtual void WriteFooter(); + int AreaLevel(std::string caption); + + + template<typename A> + bool IsElementInVector(const std::vector<A> &vec, A& el) { + typename std::vector<A>::const_iterator it; + it = std::find (vec.begin(), vec.end(), el); + if(it==vec.end()) { + return false; + } else { + return true; + } + } }; @@ -74,53 +74,53 @@ class IODispatcher { class TrajectoriesFLAT:public IODispatcher { - public: - TrajectoriesFLAT(); - virtual ~TrajectoriesFLAT(){}; +public: + TrajectoriesFLAT(); + virtual ~TrajectoriesFLAT() {}; - virtual void WriteHeader(int nPeds, double fps, Building* building, int seed); - virtual void WriteGeometry(Building* building); - virtual void WriteFrame(int frameNr, Building* building); - virtual void WriteFooter(); + virtual void WriteHeader(int nPeds, double fps, Building* building, int seed); + virtual void WriteGeometry(Building* building); + virtual void WriteFrame(int frameNr, Building* building); + virtual void WriteFooter(); }; class TrajectoriesVTK:public IODispatcher { - public: - TrajectoriesVTK(); - virtual ~TrajectoriesVTK(){}; +public: + TrajectoriesVTK(); + virtual ~TrajectoriesVTK() {}; - virtual void WriteHeader(int nPeds, double fps, Building* building, int seed); - virtual void WriteGeometry(Building* building); - virtual void WriteFrame(int frameNr, Building* building); - virtual void WriteFooter(); + virtual void WriteHeader(int nPeds, double fps, Building* building, int seed); + virtual void WriteGeometry(Building* building); + virtual void WriteFrame(int frameNr, Building* building); + virtual void WriteFooter(); }; class TrajectoriesXML_MESH:public IODispatcher { - public: - TrajectoriesXML_MESH(){}; - virtual ~TrajectoriesXML_MESH(){}; +public: + TrajectoriesXML_MESH() {}; + virtual ~TrajectoriesXML_MESH() {}; - //virtual void WriteHeader(int nPeds, double fps, Building* building, int seed); - //virtual void WriteFrame(int frameNr, Building* building); - //virtual void WriteFooter(); - virtual void WriteGeometry(Building* building); + //virtual void WriteHeader(int nPeds, double fps, Building* building, int seed); + //virtual void WriteFrame(int frameNr, Building* building); + //virtual void WriteFooter(); + virtual void WriteGeometry(Building* building); }; class TrajectoriesJPSV06: public IODispatcher { - public: - TrajectoriesJPSV06(){}; - virtual ~TrajectoriesJPSV06(){}; +public: + TrajectoriesJPSV06() {}; + virtual ~TrajectoriesJPSV06() {}; - virtual void WriteHeader(int nPeds, double fps, Building* building, int seed); - virtual void WriteGeometry(Building* building); - virtual void WriteFrame(int frameNr, Building* building); - virtual void WriteFooter(); + virtual void WriteHeader(int nPeds, double fps, Building* building, int seed); + virtual void WriteGeometry(Building* building); + virtual void WriteFrame(int frameNr, Building* building); + virtual void WriteFooter(); }; #endif /* _IODISPATCHER_H */ diff --git a/IO/OutputHandler.cpp b/IO/OutputHandler.cpp index b6fc674a22862aefc0cb9cfee53df48f8dda01fe..6fc4747993efd8c86ef383c653206f5bc2d07826 100644 --- a/IO/OutputHandler.cpp +++ b/IO/OutputHandler.cpp @@ -34,92 +34,101 @@ using namespace std; -void OutputHandler::Write(string str) { - if (this != NULL) - cout << str << endl; +void OutputHandler::Write(string str) +{ + if (this != NULL) + cout << str << endl; } -void OutputHandler::Write(const char* message,...) { - char msg[CLENGTH]; - va_list ap; - va_start (ap, message); - vsprintf (msg,message ,ap); - va_end (ap); - - string str(msg); - if(str.find("ERROR")==string::npos) { - cout<<msg<<endl; - cout.flush(); - } - else { - cerr<<msg<<endl; - cerr.flush(); - } - - //cout << "\033[1;30mbold red text\033[0m\n"; - //cout << "\033[1;31"<<msg<<"\033[0m\n"; - //cout << "\033[1;31 bla bla \033[0m\n"; +void OutputHandler::Write(const char* message,...) +{ + char msg[CLENGTH]; + va_list ap; + va_start (ap, message); + vsprintf (msg,message ,ap); + va_end (ap); + + string str(msg); + if(str.find("ERROR")==string::npos) { + cout<<msg<<endl; + cout.flush(); + } else { + cerr<<msg<<endl; + cerr.flush(); + } + + //cout << "\033[1;30mbold red text\033[0m\n"; + //cout << "\033[1;31"<<msg<<"\033[0m\n"; + //cout << "\033[1;31 bla bla \033[0m\n"; } -void STDIOHandler::Write(string str) { - if (this != NULL) - cout << str << endl; +void STDIOHandler::Write(string str) +{ + if (this != NULL) + cout << str << endl; } -FileHandler::FileHandler(const char *fn) { - pfp.open(fn); - if (!fn) { - char tmp[CLENGTH]; - sprintf(tmp, "Error!!! File [%s] could not be opened!", fn); - cerr << tmp << endl; - exit(0); - } +FileHandler::FileHandler(const char *fn) +{ + pfp.open(fn); + if (!fn) { + char tmp[CLENGTH]; + sprintf(tmp, "Error!!! File [%s] could not be opened!", fn); + cerr << tmp << endl; + exit(0); + } } -FileHandler::~FileHandler() { - pfp.close(); +FileHandler::~FileHandler() +{ + pfp.close(); } -void FileHandler::Write(string str) { - if (this != NULL) { - pfp << str << endl; - pfp.flush(); - } +void FileHandler::Write(string str) +{ + if (this != NULL) { + pfp << str << endl; + pfp.flush(); + } } -void FileHandler::Write(const char* string,...) { - char msg[CLENGTH]; - va_list ap; - va_start (ap, string); - vsprintf (msg,string ,ap); - va_end (ap); - pfp<<msg<<endl; - pfp.flush(); +void FileHandler::Write(const char* string,...) +{ + char msg[CLENGTH]; + va_list ap; + va_start (ap, string); + vsprintf (msg,string ,ap); + va_end (ap); + pfp<<msg<<endl; + pfp.flush(); } -TraVisToHandler::TraVisToHandler(string host, int port) { - client = new TraVisToClient(host, port); - brokentags.push_back("<trajectories>"); - brokentags.push_back("</trajectories>"); - brokentags.push_back("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); +TraVisToHandler::TraVisToHandler(string host, int port) +{ + client = new TraVisToClient(host, port); + brokentags.push_back("<trajectories>"); + brokentags.push_back("</trajectories>"); + brokentags.push_back("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); } -TraVisToHandler::~TraVisToHandler(){ - delete client; +TraVisToHandler::~TraVisToHandler() +{ + delete client; } -void TraVisToHandler::Write(string str) { +void TraVisToHandler::Write(string str) +{ - vector<string>::iterator str_it; + vector<string>::iterator str_it; - //There are a few broken tags which need to be checked for and removed. - for (str_it = brokentags.begin(); str_it != brokentags.end(); ++str_it) { - int tagstart = str.find(*str_it); - if (tagstart != (int) string::npos) { - str.erase(str.begin() + tagstart, str.begin() + tagstart + (*str_it).size()); - } - } - client->sendData(str.c_str()); + //There are a few broken tags which need to be checked for and removed. + for (str_it = brokentags.begin(); str_it != brokentags.end(); ++str_it) { + int tagstart = str.find(*str_it); + if (tagstart != (int) string::npos) { + str.erase(str.begin() + tagstart, str.begin() + tagstart + (*str_it).size()); + } + } + client->sendData(str.c_str()); } diff --git a/IO/OutputHandler.h b/IO/OutputHandler.h index e63beaccfbd25bb9a61f668ead0e33c91d9d9298..4ac76a2f1c158a3609c06662e3c0e49b844c98b8 100644 --- a/IO/OutputHandler.h +++ b/IO/OutputHandler.h @@ -37,39 +37,39 @@ #include "../general/Macros.h" class OutputHandler { - public: - virtual void Write(std::string str); - virtual void Write(const char *string, ...); - virtual ~OutputHandler(){}; +public: + virtual void Write(std::string str); + virtual void Write(const char *string, ...); + virtual ~OutputHandler() {}; }; class STDIOHandler : public OutputHandler { - public: - void Write(std::string str); +public: + void Write(std::string str); }; class FileHandler : public OutputHandler { - private: - std::ofstream pfp; - - public: - FileHandler(const char *fn); - virtual ~FileHandler(); - void Write(std::string str); - void Write(const char *string,...); +private: + std::ofstream pfp; + +public: + FileHandler(const char *fn); + virtual ~FileHandler(); + void Write(std::string str); + void Write(const char *string,...); }; class TraVisToHandler : public OutputHandler { - private: - TraVisToClient* client; +private: + TraVisToClient* client; - public: - TraVisToHandler(std::string host, int port); - virtual ~TraVisToHandler(); - void Write(std::string str); +public: + TraVisToHandler(std::string host, int port); + virtual ~TraVisToHandler(); + void Write(std::string str); - //Some tags are broken - std::vector<std::string> brokentags; + //Some tags are broken + std::vector<std::string> brokentags; }; diff --git a/IO/TraVisToClient.cpp b/IO/TraVisToClient.cpp index 2ece7bf8468b06f34e0086d84490112408481bb7..7312e378c9d1c4ee18760629ebe9030ce56a3501 100644 --- a/IO/TraVisToClient.cpp +++ b/IO/TraVisToClient.cpp @@ -38,103 +38,108 @@ using namespace std; -TraVisToClient::TraVisToClient(string hostname, unsigned short port) { - _hostname=hostname; - _port = port; - _isConnected = false; - createConnection(); +TraVisToClient::TraVisToClient(string hostname, unsigned short port) +{ + _hostname=hostname; + _port = port; + _isConnected = false; + createConnection(); } -TraVisToClient::~TraVisToClient() { - if (_isConnected) close(); +TraVisToClient::~TraVisToClient() +{ + if (_isConnected) close(); } /// send datablock to the server -void TraVisToClient::sendData(const char* data) { +void TraVisToClient::sendData(const char* data) +{ - // first create a new connection, in the case the last one was lost/close + // first create a new connection, in the case the last one was lost/close - if (!_isConnected) { - createConnection(); - //FIXME: queue messsage in a vector - // msgQueue.push_back(data); - return; + if (!_isConnected) { + createConnection(); + //FIXME: queue messsage in a vector + // msgQueue.push_back(data); + return; - } - char msgSizeStr[10]; - int msgSize = (int)strlen(data); - sprintf(msgSizeStr, "%d\n", msgSize); + } + char msgSizeStr[10]; + int msgSize = (int)strlen(data); + sprintf(msgSizeStr, "%d\n", msgSize); - /* check if parameters are valid */ - if (NULL == data) { - fprintf(stderr, "invalid message buffer!"); - fprintf(stderr, "leaving sendMessage()"); - _isConnected = false; - return; - } + /* check if parameters are valid */ + if (NULL == data) { + fprintf(stderr, "invalid message buffer!"); + fprintf(stderr, "leaving sendMessage()"); + _isConnected = false; + return; + } - // do until queue empty for() + // do until queue empty for() - /*send the length of the message*/ - int msgsize = strlen(msgSizeStr); - if (msgsize != send(_tcpSocket, (const char *) msgSizeStr, strlen(msgSizeStr), 0)) { - fprintf(stderr, "sending message Size failed"); - fprintf(stderr, "leaving sendMessage()"); - _isConnected = false; - return; - } + /*send the length of the message*/ + int msgsize = strlen(msgSizeStr); + if (msgsize != send(_tcpSocket, (const char *) msgSizeStr, strlen(msgSizeStr), 0)) { + fprintf(stderr, "sending message Size failed"); + fprintf(stderr, "leaving sendMessage()"); + _isConnected = false; + return; + } - /* now send the message */ - if (msgSize != send(_tcpSocket, (const char *) data, msgSize, 0)) { - fprintf(stderr, "sending message failed"); - fprintf(stderr, "leaving sendMessage()"); - _isConnected = false; - return; - } + /* now send the message */ + if (msgSize != send(_tcpSocket, (const char *) data, msgSize, 0)) { + fprintf(stderr, "sending message failed"); + fprintf(stderr, "leaving sendMessage()"); + _isConnected = false; + return; + } - // end do + // end do } /// close the client (end the connection) -void TraVisToClient::close() { - if (_isConnected) { - /* all things are done, so shutdown the connection */ - if (!shutdownAndCloseSocket(_tcpSocket)) { - fprintf(stderr, "shutdown and close socket failed!"); - stopSocketSession(); - fprintf(stderr, "leaving main() with error"); - return; - } - - /* stop the socket session */ - stopSocketSession(); - } +void TraVisToClient::close() +{ + if (_isConnected) { + /* all things are done, so shutdown the connection */ + if (!shutdownAndCloseSocket(_tcpSocket)) { + fprintf(stderr, "shutdown and close socket failed!"); + stopSocketSession(); + fprintf(stderr, "leaving main() with error"); + return; + } + + /* stop the socket session */ + stopSocketSession(); + } } -void TraVisToClient::createConnection() { - - /* start the socket session */ - if (!startSocketSession()) { - fprintf(stderr, "startSocketSession() failed!"); - fprintf(stderr, "socket creation failed for host [%s] on port [%d]!",_hostname.c_str(),_port); - exit(EXIT_FAILURE); - } - - /* create a new socket and connect the socket to the given service */ - if (INVALID_SOCKET == (_tcpSocket = createClientSocket(_hostname.c_str(), _port))) { - fprintf(stderr, "\nsocket creation failed for host [%s] on port [%d]!\n",_hostname.c_str(),_port); - stopSocketSession(); - exit(EXIT_FAILURE); - } - _isConnected = true; +void TraVisToClient::createConnection() +{ + + /* start the socket session */ + if (!startSocketSession()) { + fprintf(stderr, "startSocketSession() failed!"); + fprintf(stderr, "socket creation failed for host [%s] on port [%d]!",_hostname.c_str(),_port); + exit(EXIT_FAILURE); + } + + /* create a new socket and connect the socket to the given service */ + if (INVALID_SOCKET == (_tcpSocket = createClientSocket(_hostname.c_str(), _port))) { + fprintf(stderr, "\nsocket creation failed for host [%s] on port [%d]!\n",_hostname.c_str(),_port); + stopSocketSession(); + exit(EXIT_FAILURE); + } + _isConnected = true; } /********* function definitions **************************************/ @@ -151,32 +156,33 @@ void TraVisToClient::createConnection() { * @c INADDR_NONE. */ unsigned long -TraVisToClient::lookupHostAddress(const char *hostName) { - unsigned long addr; /* inet address of hostname */ - struct hostent *host; /* host structure for DNS request */ +TraVisToClient::lookupHostAddress(const char *hostName) +{ + unsigned long addr; /* inet address of hostname */ + struct hostent *host; /* host structure for DNS request */ - dtrace("entering lookupHostAddress()"); + dtrace("entering lookupHostAddress()"); - if (NULL == hostName) { - derror("invalid parameter"); - dtrace("leaving lookupHostAddress()"); - return (INADDR_NONE); - } + if (NULL == hostName) { + derror("invalid parameter"); + dtrace("leaving lookupHostAddress()"); + return (INADDR_NONE); + } - dtrace("looking for host %s", hostName); + dtrace("looking for host %s", hostName); - addr = inet_addr(hostName); + addr = inet_addr(hostName); - if (INADDR_NONE == addr) { - /* hostName isn't a dotted IP, so resolve it through DNS */ - host = gethostbyname(hostName); - if (NULL != host) { - addr = *((unsigned long *) host->h_addr); - } - } + if (INADDR_NONE == addr) { + /* hostName isn't a dotted IP, so resolve it through DNS */ + host = gethostbyname(hostName); + if (NULL != host) { + addr = *((unsigned long *) host->h_addr); + } + } - dtrace("leaving lookupHostAddress()"); - return (addr); + dtrace("leaving lookupHostAddress()"); + return (addr); } /******** end of function lookupHostAddress **************************/ @@ -192,46 +198,47 @@ TraVisToClient::lookupHostAddress(const char *hostName) { * returns @c INVALID_SOCKET. */ socket_t -TraVisToClient::createClientSocket(const char *serverName, unsigned short portNumber) { - unsigned long ipAddress; /* internet address */ - struct sockaddr_in srvAddr; /* server's internet socket address */ - socket_t sock; /* file descriptor for client socket */ - - dtrace("entering createClientSocket()"); - - /* get the IP address of the server host */ - if (INADDR_NONE == (ipAddress = lookupHostAddress(serverName))) { - derror("lookupHostAddress() failed"); - dtrace("leaving createClientSocket() with INVALID_SOCKET"); - return (INVALID_SOCKET); - } - - dtrace("trying to connect %s on port %hu", serverName, portNumber); - - /* create the client socket */ - if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP))) { - derror("socket creation failed"); - dtrace("leaving createClientSocket() with INVALID_SOCKET"); - return (INVALID_SOCKET); - } - - /* fill the server address structure */ - memset(&srvAddr, 0, sizeof (srvAddr)); - srvAddr.sin_family = AF_INET; - srvAddr.sin_port = htons(portNumber); - srvAddr.sin_addr.s_addr = ipAddress; - - /* try to connect to the server socket */ - if (SOCKET_ERROR == connect(sock, (struct sockaddr *) & srvAddr, sizeof (srvAddr))) { - derror("connect() failed"); - //FIXME - //closesocket(tcpSocket); - dtrace("leaving createClientSocket() with INVALID_SOCKET"); - return (INVALID_SOCKET); - } - - dtrace("leaving createClientSocket()"); - return (sock); +TraVisToClient::createClientSocket(const char *serverName, unsigned short portNumber) +{ + unsigned long ipAddress; /* internet address */ + struct sockaddr_in srvAddr; /* server's internet socket address */ + socket_t sock; /* file descriptor for client socket */ + + dtrace("entering createClientSocket()"); + + /* get the IP address of the server host */ + if (INADDR_NONE == (ipAddress = lookupHostAddress(serverName))) { + derror("lookupHostAddress() failed"); + dtrace("leaving createClientSocket() with INVALID_SOCKET"); + return (INVALID_SOCKET); + } + + dtrace("trying to connect %s on port %hu", serverName, portNumber); + + /* create the client socket */ + if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP))) { + derror("socket creation failed"); + dtrace("leaving createClientSocket() with INVALID_SOCKET"); + return (INVALID_SOCKET); + } + + /* fill the server address structure */ + memset(&srvAddr, 0, sizeof (srvAddr)); + srvAddr.sin_family = AF_INET; + srvAddr.sin_port = htons(portNumber); + srvAddr.sin_addr.s_addr = ipAddress; + + /* try to connect to the server socket */ + if (SOCKET_ERROR == connect(sock, (struct sockaddr *) & srvAddr, sizeof (srvAddr))) { + derror("connect() failed"); + //FIXME + //closesocket(tcpSocket); + dtrace("leaving createClientSocket() with INVALID_SOCKET"); + return (INVALID_SOCKET); + } + + dtrace("leaving createClientSocket()"); + return (sock); } /******** end of function createClientSocket *************************/ @@ -244,46 +251,47 @@ TraVisToClient::createClientSocket(const char *serverName, unsigned short portNu * If an error occurs, the function returns @c INVALID_SOCKET. */ socket_t -TraVisToClient::createServerSocket(unsigned short portNumber) { - struct sockaddr_in srvAddr; /* server's internet socket address */ - socket_t sock; /* file descriptor for server socket */ - - dtrace("entering createServerSocket()"); - - /* create the server socket */ - if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP))) { - derror("socket creation failed"); - dtrace("leaving createServerSocket() with INVALID_SOCKET"); - return (INVALID_SOCKET); - } - - /* fill the server address structure */ - /* first of all, zero srvAddr, so that we have a defined status */ - memset(&srvAddr, 0, sizeof (srvAddr)); - srvAddr.sin_family = AF_INET; - srvAddr.sin_port = htons(portNumber); - srvAddr.sin_addr.s_addr = htonl(INADDR_ANY); - - /* try to bind socket to the specified server port */ - if (SOCKET_ERROR == bind(sock, (struct sockaddr *) & srvAddr, sizeof (srvAddr))) { - derror("bind() failed!"); - //FIXME: - //closesocket(tcpSocket); - dtrace("leaving createServerSocket() with INVALID_SOCKET"); - return (INVALID_SOCKET); - } - - if (SOCKET_ERROR == listen(sock, QUEUE_LENGTH)) { - derror("listen() failed!"); - shutdownAndCloseSocket(sock); - dtrace("leaving createServerSocket() with INVALID_SOCKET"); - return (INVALID_SOCKET); - } - - dtrace("server started at port %hu", portNumber); - - dtrace("leaving createServerSocket()"); - return (sock); +TraVisToClient::createServerSocket(unsigned short portNumber) +{ + struct sockaddr_in srvAddr; /* server's internet socket address */ + socket_t sock; /* file descriptor for server socket */ + + dtrace("entering createServerSocket()"); + + /* create the server socket */ + if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP))) { + derror("socket creation failed"); + dtrace("leaving createServerSocket() with INVALID_SOCKET"); + return (INVALID_SOCKET); + } + + /* fill the server address structure */ + /* first of all, zero srvAddr, so that we have a defined status */ + memset(&srvAddr, 0, sizeof (srvAddr)); + srvAddr.sin_family = AF_INET; + srvAddr.sin_port = htons(portNumber); + srvAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + /* try to bind socket to the specified server port */ + if (SOCKET_ERROR == bind(sock, (struct sockaddr *) & srvAddr, sizeof (srvAddr))) { + derror("bind() failed!"); + //FIXME: + //closesocket(tcpSocket); + dtrace("leaving createServerSocket() with INVALID_SOCKET"); + return (INVALID_SOCKET); + } + + if (SOCKET_ERROR == listen(sock, QUEUE_LENGTH)) { + derror("listen() failed!"); + shutdownAndCloseSocket(sock); + dtrace("leaving createServerSocket() with INVALID_SOCKET"); + return (INVALID_SOCKET); + } + + dtrace("server started at port %hu", portNumber); + + dtrace("leaving createServerSocket()"); + return (sock); } /******** end of function createServerSocket *************************/ @@ -299,33 +307,34 @@ TraVisToClient::createServerSocket(unsigned short portNumber) { * otherwise the function returns @c false. */ bool -TraVisToClient::sendMessage(socket_t sock, const void *msg, int msgSize) { - dtrace("entering sendMessage()"); - - /* check if parameters are valid */ - if (NULL == msg) { - derror("invalid message buffer!"); - dtrace("leaving sendMessage()"); - return (false); - } - - if (0 >= msgSize) { - derror("invalid message size %d", msgSize); - dtrace("leaving sendMessage()"); - return (false); - } - - dtrace("sending message of size %d", msgSize); - - /* now send the message */ - if (msgSize != send(sock, (const char *) msg, msgSize, 0)) { - derror("sending message failed"); - dtrace("leaving sendMessage()"); - return (false); - } - - dtrace("leaving sendMessage()"); - return (true); +TraVisToClient::sendMessage(socket_t sock, const void *msg, int msgSize) +{ + dtrace("entering sendMessage()"); + + /* check if parameters are valid */ + if (NULL == msg) { + derror("invalid message buffer!"); + dtrace("leaving sendMessage()"); + return (false); + } + + if (0 >= msgSize) { + derror("invalid message size %d", msgSize); + dtrace("leaving sendMessage()"); + return (false); + } + + dtrace("sending message of size %d", msgSize); + + /* now send the message */ + if (msgSize != send(sock, (const char *) msg, msgSize, 0)) { + derror("sending message failed"); + dtrace("leaving sendMessage()"); + return (false); + } + + dtrace("leaving sendMessage()"); + return (true); } /******** end of function sendMessage ********************************/ @@ -343,57 +352,58 @@ TraVisToClient::sendMessage(socket_t sock, const void *msg, int msgSize) { * the function returns @c false. */ bool -TraVisToClient::receiveMessage(socket_t sock, void *msg, int msgSize) { - char *msgPart; /* pointer to the memory for receiving the message */ - int toReceive; /* number of bytes to receive */ - int received; /* number of bytes totally received */ - int nBytes; /* number of bytes currently received */ - - dtrace("entering receiveMessage()"); - - /* check if parameters are valid */ - if (NULL == msg) { - derror("invalid message buffer!"); - dtrace("leaving receiveMessage()"); - return (false); - } - - if (0 >= msgSize) { - derror("invalid message size!"); - dtrace("leaving receiveMessage()"); - return (false); - } - - msgPart = (char *) msg; - received = 0; - - dtrace("trying to receive a message of size %d", msgSize); - - /* start receiving bytes from server until complete message is received */ - do { - toReceive = msgSize - received; - nBytes = recv(sock, msgPart, toReceive, 0); - switch (nBytes) { - case SOCKET_ERROR: /* error occurred */ - derror("error during message receipt"); - dtrace("leaving receiveMessage()"); - return (false); - case 0: /* connection has been closed */ - derror("remote host has closed the connection"); - dtrace("leaving receiveMessage()"); - return (false); - default: /* some bytes have been received */ - dtrace("received %d bytes of message", nBytes); - received += nBytes; - msgPart += nBytes; - break; - } - } while (received != msgSize); - - dtrace("received message of size %d", received); - - dtrace("leaving receiveMessage()"); - return (true); +TraVisToClient::receiveMessage(socket_t sock, void *msg, int msgSize) +{ + char *msgPart; /* pointer to the memory for receiving the message */ + int toReceive; /* number of bytes to receive */ + int received; /* number of bytes totally received */ + int nBytes; /* number of bytes currently received */ + + dtrace("entering receiveMessage()"); + + /* check if parameters are valid */ + if (NULL == msg) { + derror("invalid message buffer!"); + dtrace("leaving receiveMessage()"); + return (false); + } + + if (0 >= msgSize) { + derror("invalid message size!"); + dtrace("leaving receiveMessage()"); + return (false); + } + + msgPart = (char *) msg; + received = 0; + + dtrace("trying to receive a message of size %d", msgSize); + + /* start receiving bytes from server until complete message is received */ + do { + toReceive = msgSize - received; + nBytes = recv(sock, msgPart, toReceive, 0); + switch (nBytes) { + case SOCKET_ERROR: /* error occurred */ + derror("error during message receipt"); + dtrace("leaving receiveMessage()"); + return (false); + case 0: /* connection has been closed */ + derror("remote host has closed the connection"); + dtrace("leaving receiveMessage()"); + return (false); + default: /* some bytes have been received */ + dtrace("received %d bytes of message", nBytes); + received += nBytes; + msgPart += nBytes; + break; + } + } while (received != msgSize); + + dtrace("received message of size %d", received); + + dtrace("leaving receiveMessage()"); + return (true); } /******** end of function receiveMessage *****************************/ @@ -406,30 +416,32 @@ TraVisToClient::receiveMessage(socket_t sock, void *msg, int msgSize) { * @c false */ bool -TraVisToClient::shutdownAndCloseSocket(socket_t sock) { - bool status = true; +TraVisToClient::shutdownAndCloseSocket(socket_t sock) +{ + bool status = true; - dtrace("entering shutdownAndCloseSocket()"); + dtrace("entering shutdownAndCloseSocket()"); - if (SOCKET_ERROR == shutdown(sock, SHUT_RDWR)) { - derror("shutdown() failed"); - status = false; - } + if (SOCKET_ERROR == shutdown(sock, SHUT_RDWR)) { + derror("shutdown() failed"); + status = false; + } - //FIXME: - //if (SOCKET_ERROR == closesocket(tcpSocket)) { - // derror("closesocket() failed"); - // status = false; - //} + //FIXME: + //if (SOCKET_ERROR == closesocket(tcpSocket)) { + // derror("closesocket() failed"); + // status = false; + //} - dtrace("leaving shutdownAndCloseSocket()"); - return (status); + dtrace("leaving shutdownAndCloseSocket()"); + return (status); } /******** end of function shutdownAndCloseSocket *********************/ void -TraVisToClient::_printErrorMessage(void) { +TraVisToClient::_printErrorMessage(void) +{ } @@ -442,38 +454,39 @@ TraVisToClient::_printErrorMessage(void) { * @c false */ bool -TraVisToClient::_startWin32SocketSession(void) { - WORD requestedVersion; - WSADATA wsaData; - - dtrace("entering _startWin32SocketSession()"); - - requestedVersion = MAKEWORD(WS_MAJOR_VERSION, WS_MINOR_VERSION); - - if (0 != WSAStartup(requestedVersion, &wsaData)) { - derror("WSAStartup() failed"); - dtrace("leaving _startWin32SocketSession() with error"); - return (false); - } - - /* Confirm that the Windows Socket DLL supports 1.1. */ - /* Note that if the DLL supports versions greater */ - /* than 1.1 in addition to 1.1, it will still return */ - /* 1.1 in wVersion since that is the version we */ - /* requested. */ - - if (WS_MINOR_VERSION != LOBYTE(wsaData.wVersion) - || WS_MAJOR_VERSION != HIBYTE(wsaData.wVersion)) { - derror("Windows Socket DLL does not support the requested version"); - _stopWin32SocketSession(); - dtrace("leaving _startWin32SocketSession() with error"); - return (false); - } - - WSASetLastError(0); /* reset the error code */ - - dtrace("leaving _startWin32SocketSession()"); - return (true); +TraVisToClient::_startWin32SocketSession(void) +{ + WORD requestedVersion; + WSADATA wsaData; + + dtrace("entering _startWin32SocketSession()"); + + requestedVersion = MAKEWORD(WS_MAJOR_VERSION, WS_MINOR_VERSION); + + if (0 != WSAStartup(requestedVersion, &wsaData)) { + derror("WSAStartup() failed"); + dtrace("leaving _startWin32SocketSession() with error"); + return (false); + } + + /* Confirm that the Windows Socket DLL supports 1.1. */ + /* Note that if the DLL supports versions greater */ + /* than 1.1 in addition to 1.1, it will still return */ + /* 1.1 in wVersion since that is the version we */ + /* requested. */ + + if (WS_MINOR_VERSION != LOBYTE(wsaData.wVersion) + || WS_MAJOR_VERSION != HIBYTE(wsaData.wVersion)) { + derror("Windows Socket DLL does not support the requested version"); + _stopWin32SocketSession(); + dtrace("leaving _startWin32SocketSession() with error"); + return (false); + } + + WSASetLastError(0); /* reset the error code */ + + dtrace("leaving _startWin32SocketSession()"); + return (true); } /******** end of function _startWin32SocketSession *******************/ @@ -482,15 +495,16 @@ TraVisToClient::_startWin32SocketSession(void) { * No future API calls are allowed. */ void -TraVisToClient::_stopWin32SocketSession(void) { - dtrace("entering _stopWin32SocketSession()"); +TraVisToClient::_stopWin32SocketSession(void) +{ + dtrace("entering _stopWin32SocketSession()"); - if (SOCKET_ERROR == WSACleanup()) { - derror("WSACleanup() failed"); - } + if (SOCKET_ERROR == WSACleanup()) { + derror("WSACleanup() failed"); + } - dtrace("leaving _stopWin32SocketSession()"); - return; + dtrace("leaving _stopWin32SocketSession()"); + return; } /******** end of function _stopWin32SocketSession ********************/ diff --git a/IO/TraVisToClient.h b/IO/TraVisToClient.h index b4033a2b8429edbbacd0247e034ce22584c69196..9cc8624dc153c15e844c4bd1fd6b4af251913f8c 100644 --- a/IO/TraVisToClient.h +++ b/IO/TraVisToClient.h @@ -91,58 +91,58 @@ typedef int socket_t; #define HOST "localhost" class TraVisToClient { - public: +public: - /// create a client with specific parameters - TraVisToClient(std::string hostname = HOST, unsigned short port = PORT); + /// create a client with specific parameters + TraVisToClient(std::string hostname = HOST, unsigned short port = PORT); - /// Destructor - virtual ~TraVisToClient(); + /// Destructor + virtual ~TraVisToClient(); - /// send datablock to the server - /// this functions is still blocking unfortunately, so it may - /// influence the execution time of your program - void sendData(const char* data); + /// send datablock to the server + /// this functions is still blocking unfortunately, so it may + /// influence the execution time of your program + void sendData(const char* data); - /// close the client (end the connection) - void close(); + /// close the client (end the connection) + void close(); - /// send a datagram using the unreliable - /// udp protokoll - void sendDatagram(char *datagram); + /// send a datagram using the unreliable + /// udp protokoll + void sendDatagram(char *datagram); - private: - void createConnection(); +private: + void createConnection(); - unsigned long lookupHostAddress(const char *hostName); + unsigned long lookupHostAddress(const char *hostName); - socket_t createClientSocket(const char *serverName, unsigned short portNumber); + socket_t createClientSocket(const char *serverName, unsigned short portNumber); - socket_t createServerSocket(unsigned short portNumber); + socket_t createServerSocket(unsigned short portNumber); - bool shutdownAndCloseSocket(socket_t sock); + bool shutdownAndCloseSocket(socket_t sock); - bool sendMessage(socket_t sock, const void *msg, int msgSize); + bool sendMessage(socket_t sock, const void *msg, int msgSize); - bool receiveMessage(socket_t sock, void *msg, int msgSize); + bool receiveMessage(socket_t sock, void *msg, int msgSize); - void _printErrorMessage(void); + void _printErrorMessage(void); #ifdef _WIN32 - bool _startWin32SocketSession(void); - void _stopWin32SocketSession(void); + bool _startWin32SocketSession(void); + void _stopWin32SocketSession(void); #else #define closesocket close #endif - private: - bool _isConnected; - socket_t _tcpSocket; - std::string _hostname; - unsigned short _port; - std::vector<const char *> _msgQueue; +private: + bool _isConnected; + socket_t _tcpSocket; + std::string _hostname; + unsigned short _port; + std::vector<const char *> _msgQueue; }; diff --git a/Simulation.cpp b/Simulation.cpp index 90e1395232513697a465a741090c5ea345cd8561..e4c523b89abdde30256580849a8892e73787aece 100644 --- a/Simulation.cpp +++ b/Simulation.cpp @@ -1,3 +1,4 @@ + /** * @file Simulation.cpp * @date Created on: Dec 15, 2010 @@ -32,29 +33,31 @@ using namespace std; -Simulation::Simulation() { - _nPeds = 0; - _tmax = 0; - _seed=8091983; - _deltaT = 0; - _building = NULL; - _distribution = NULL; - _direction = NULL; - _model = NULL; - _solver = NULL; - _iod = new IODispatcher(); - _fps=1; - _em=NULL; +Simulation::Simulation() +{ + _nPeds = 0; + _tmax = 0; + _seed=8091983; + _deltaT = 0; + _building = NULL; + _distribution = NULL; + _direction = NULL; + _model = NULL; + _solver = NULL; + _iod = new IODispatcher(); + _fps=1; + _em=NULL; } -Simulation::~Simulation() { - delete _building; - delete _distribution; - delete _direction; - delete _model; - delete _solver; - delete _iod; - delete _em; +Simulation::~Simulation() +{ + delete _building; + delete _distribution; + delete _direction; + delete _model; + delete _solver; + delete _iod; + delete _em; } /************************************************ @@ -62,8 +65,9 @@ Simulation::~Simulation() { ************************************************/ -void Simulation::SetPedsNumber(int i) { - _nPeds = i; +void Simulation::SetPedsNumber(int i) +{ + _nPeds = i; } @@ -72,437 +76,419 @@ void Simulation::SetPedsNumber(int i) { ************************************************/ -int Simulation::GetPedsNumber() const { - return _nPeds; +int Simulation::GetPedsNumber() const +{ + return _nPeds; } -Building * Simulation::GetBuilding() const { - return _building; +Building * Simulation::GetBuilding() const +{ + return _building; } -void Simulation::InitArgs(ArgumentParser* args) { - char tmp[CLENGTH]; - string s = "Parameter:\n"; - - _argsParser=args; - switch (args->GetLog()) { - case 0: - // no log file - //Log = new OutputHandler(); - break; - case 1: - if(Log) delete Log; - Log = new STDIOHandler(); - break; - case 2: - { - char name[CLENGTH]=""; - sprintf(name,"%s.P0.dat",args->GetErrorLogFile().c_str()); - if(Log) delete Log; - Log = new FileHandler(name); - } - break; - default: - printf("Wrong option for Logfile!\n\n"); - exit(0); - } - - - if(args->GetPort()!=-1){ - switch(args->GetFileFormat()) - { - case FORMAT_XML_PLAIN_WITH_MESH: - case FORMAT_XML_PLAIN: - { - OutputHandler* travisto = new TraVisToHandler(args->GetHostname(), - args->GetPort()); - _iod->AddIO(travisto); - break; - } - case FORMAT_XML_BIN: - { - Log->Write("INFO: \tFormat xml-bin not yet supported in streaming\n"); - exit(0); - break; - } - case FORMAT_PLAIN: - { - Log->Write("INFO: \tFormat plain not yet supported in streaming\n"); - exit(0); - break; - } - case FORMAT_VTK: - { - Log->Write("INFO: \tFormat vtk not yet supported in streaming\n"); - exit(0); - break; - } - } - - s.append("\tonline streaming enabled \n"); - } - - if(args->GetTrajectoriesFile().empty()==false) - { - switch (args->GetFileFormat()) - { - case FORMAT_XML_PLAIN: - { - OutputHandler* tofile = new FileHandler(args->GetTrajectoriesFile().c_str()); - _iod->AddIO(tofile); - break; - } - case FORMAT_XML_PLAIN_WITH_MESH: - { - OutputHandler* tofile = new FileHandler(args->GetTrajectoriesFile().c_str()); - if(_iod) delete _iod; - _iod = new TrajectoriesXML_MESH(); - _iod->AddIO(tofile); - break; - } - case FORMAT_XML_BIN: - { - OutputHandler* tofile = new FileHandler(args->GetTrajectoriesFile().c_str()); - if(_iod) delete _iod; - _iod = new TrajectoriesJPSV06(); - _iod->AddIO(tofile); - //Log->Write("INFO: \tFormat xml-bin not yet supported\n"); - //exit(0); - break; - } - case FORMAT_PLAIN: - { - Log->Write("INFO: \tFormat plain not yet supported\n"); - OutputHandler* file = new FileHandler(args->GetTrajectoriesFile().c_str()); - - if(_iod) delete _iod; - _iod = new TrajectoriesFLAT(); - _iod->AddIO(file); - //Log->Write("INFO: \tFormat plain maybe not yet implemented ?"); - //exit(0); - break; - } - case FORMAT_VTK: - { - Log->Write("INFO: \tFormat vtk not yet supported\n"); - OutputHandler* file = new FileHandler((args->GetTrajectoriesFile() +".vtk").c_str()); - - if(_iod) delete _iod; - _iod = new TrajectoriesVTK(); - _iod->AddIO(file); - //exit(0); - break; - } - } - - } - - - _distribution = new PedDistributor(args->GetV0Mu(), args->GetV0Sigma(), args->GetBmaxMu(), - args->GetBmaxSigma(), args->GetBminMu(), args->GetBminSigma(), args->GetAtauMu(), - args->GetAtauSigma(), args->GetAminMu(), args->GetAminSigma(), args->GetTauMu(), - args->GetTauSigma()); - s.append(_distribution->writeParameter()); - _distribution->InitDistributor(args->GetProjectFile()); - // define how the navigation line is crossed - int direction = args->GetExitStrategy(); - sprintf(tmp, "\tDirection to the exit: %d\n", direction); - s.append(tmp); - switch (direction) { - case 1: - _direction = new DirectionMiddlePoint(); - break; - case 2: - _direction = new DirectionMinSeperation(); - break; - case 3: - _direction = new DirectionMinSeperationShorterLine(); - break; - case 4: - _direction = new DirectionInRangeBottleneck(); - break; - case 5: - _direction = new DirectionGeneral(); - break; - default: - cout<<"Direction strategy not available. Exit"<<endl; - exit(EXIT_FAILURE); - break; - } - int model = args->GetModel(); - if(model == 1) //GCFM - { - _model = new GCFMModel(_direction, args->GetNuPed(), args->GetNuWall(), args->GetDistEffMaxPed(), - args->GetDistEffMaxWall(), args->GetIntPWidthPed(), args->GetIntPWidthWall(), - args->GetMaxFPed(), args->GetMaxFWall()); - s.append("\tModel: GCFMModel\n"); - s.append(_model->writeParameter()); - } - else if (model == 2)//Gompertz - { - _model = new GompertzModel(_direction, args->GetNuPed(), args->GetNuWall() ); - s.append("\tModel: GompertzModel\n"); - s.append(_model->writeParameter()); - } - // ODE solver - int solver = args->GetSolver(); - sprintf(tmp, "\tODE Loeser: %d\n", solver); - s.append(tmp); - switch (solver) { - case 1: - _solver = new EulerSolverLC(_model); - break; - case 2: - _solver = new VelocityVerletSolver(_model); - break; - case 3: - _solver = new LeapfrogSolver(_model); - break; - } - _tmax = args->GetTmax(); - sprintf(tmp, "\tt_max: %f\n", _tmax); - s.append(tmp); - _deltaT = args->Getdt(); - sprintf(tmp, "\tdt: %f\n", _deltaT); - s.append(tmp); - - _fps=args->Getfps(); - sprintf(tmp, "\tfps: %f\n", _fps); - s.append(tmp); - - // Routing - vector< pair<int, RoutingStrategy> > routers= args->GetRoutingStrategy(); - RoutingEngine* routingEngine= new RoutingEngine(); - - for (unsigned int r= 0;r<routers.size();r++){ - - RoutingStrategy strategy=routers[r].second; - - int routerID=routers[r].first; - - switch (strategy) { - case ROUTING_LOCAL_SHORTEST: - { - Router* router=new GlobalRouter(); - router->SetID(routerID); - router->SetStrategy(strategy); - routingEngine->AddRouter(router); - s.append("\tRouting Strategy local shortest added\n"); - break; - } - case ROUTING_GLOBAL_SHORTEST: - { - - Router* router=new GlobalRouter(); - router->SetID(routerID); - router->SetStrategy(strategy); - routingEngine->AddRouter(router); - s.append("\tRouting Strategy global shortest added\n"); - break; - } - case ROUTING_QUICKEST: - { - Router* router=new QuickestPathRouter(); - router->SetID(routerID); - router->SetStrategy(strategy); - routingEngine->AddRouter(router); - s.append("\tRouting Strategy quickest path added\n"); - break; - } - case ROUTING_DYNAMIC: - { - Router* router=new GraphRouter(); - router->SetID(routerID); - router->SetStrategy(strategy); - routingEngine->AddRouter(router); - s.append("\tRouting Strategy graph router added\n"); - break; - } - case ROUTING_NAV_MESH: - { - Router* router=new MeshRouter(); - router->SetID(routerID); - router->SetStrategy(strategy); - routingEngine->AddRouter(router); - s.append("\tRouting Strategy nav_mesh router added\n"); - break; - } - case ROUTING_DUMMY: - { - Router* router=new DummyRouter(); - router->SetID(routerID); - router->SetStrategy(strategy); - routingEngine->AddRouter(router); - s.append("\tRouting Strategy dummy router added\n"); - break; - } - case ROUTING_SAFEST: - { - Router * router=new SafestPathRouter(); - router->SetID(routerID); - router->SetStrategy(strategy); - routingEngine->AddRouter(router); - s.append("\tRouting Strategy cognitive map router added\n"); - break; - } - case ROUTING_COGNITIVEMAP: - { - Router* router=new CognitiveMapRouter(); - router->SetID(routerID); - router->SetStrategy(strategy); - routingEngine->AddRouter(router); - s.append("\tRouting Strategy dummy router added\n"); - break; - } - case ROUTING_UNDEFINED: - default: - cout<<"router not available"<<endl; - exit(EXIT_FAILURE); - break; - } - } - s.append("\n"); - - // IMPORTANT: do not change the order in the following.. - _building = new Building(); - _building->SetRoutingEngine(routingEngine); - _building->SetProjectFilename(args->GetProjectFile()); - _building->SetProjectRootDir(args->GetProjectRootDir()); - - _building->LoadBuildingFromFile(); - _building->LoadRoutingInfo(args->GetProjectFile()); - //_building->AddSurroundingRoom(); - _building->InitGeometry(); // create the polygons - _building->LoadTrafficInfo(); - // in the case the navigation mesh should be written to a file - if(args->GetNavigationMesh()!=""){ - Log->Write("INFO: \tWriting the navigation mesh to: " + args->GetNavigationMesh()); - //Navigation mesh implementation - NavMesh* nv= new NavMesh(_building); - nv->BuildNavMesh(); - //nv->WriteToFile("../pedunc/examples/stadium/arena.nav"); - nv->WriteToFile(args->GetNavigationMesh()+".nav"); - nv->WriteToFileTraVisTo(args->GetNavigationMesh()); - //nv->WriteScenario(); - exit(EXIT_FAILURE); - //iod->WriteGeometryRVO(pBuilding);exit(EXIT_FAILURE); - //iod->WriteNavMeshORCA(pBuilding);exit(EXIT_FAILURE); - } - - _nPeds=_distribution->Distribute(_building); - - //using linkedcells - if (args->GetLinkedCells()){ - s.append("\tusing Linked-Cells for spatial queries\n"); - _building->InitGrid(args->GetLinkedCellSize()); - }else { - _building->InitGrid(-1); - } - - // initialize the routing engine before doing any other things - routingEngine->Init(_building); - - //this is very specific to the gcfm model - _building->InitPhiAllPeds(_deltaT); - - - //pBuilding->WriteToErrorLog(); - - //get the seed - _seed=args->GetSeed(); - - // perform a general check to the . - _building->SanityCheck(); - - //read the events - _em = new EventManager(_building); - _em->SetProjectFilename(args->GetProjectFile()); - _em->SetProjectRootDir(args->GetProjectRootDir()); - _em->readEventsXml(); - _em->listEvents(); +void Simulation::InitArgs(ArgumentParser* args) +{ + char tmp[CLENGTH]; + string s = "Parameter:\n"; + + _argsParser=args; + switch (args->GetLog()) { + case 0: + // no log file + //Log = new OutputHandler(); + break; + case 1: + if(Log) delete Log; + Log = new STDIOHandler(); + break; + case 2: { + char name[CLENGTH]=""; + sprintf(name,"%s.P0.dat",args->GetErrorLogFile().c_str()); + if(Log) delete Log; + Log = new FileHandler(name); + } + break; + default: + printf("Wrong option for Logfile!\n\n"); + exit(0); + } + + + if(args->GetPort()!=-1) { + switch(args->GetFileFormat()) { + case FORMAT_XML_PLAIN_WITH_MESH: + case FORMAT_XML_PLAIN: { + OutputHandler* travisto = new TraVisToHandler(args->GetHostname(), + args->GetPort()); + _iod->AddIO(travisto); + break; + } + case FORMAT_XML_BIN: { + Log->Write("INFO: \tFormat xml-bin not yet supported in streaming\n"); + exit(0); + break; + } + case FORMAT_PLAIN: { + Log->Write("INFO: \tFormat plain not yet supported in streaming\n"); + exit(0); + break; + } + case FORMAT_VTK: { + Log->Write("INFO: \tFormat vtk not yet supported in streaming\n"); + exit(0); + break; + } + } + + s.append("\tonline streaming enabled \n"); + } + + if(args->GetTrajectoriesFile().empty()==false) { + switch (args->GetFileFormat()) { + case FORMAT_XML_PLAIN: { + OutputHandler* tofile = new FileHandler(args->GetTrajectoriesFile().c_str()); + _iod->AddIO(tofile); + break; + } + case FORMAT_XML_PLAIN_WITH_MESH: { + OutputHandler* tofile = new FileHandler(args->GetTrajectoriesFile().c_str()); + if(_iod) delete _iod; + _iod = new TrajectoriesXML_MESH(); + _iod->AddIO(tofile); + break; + } + case FORMAT_XML_BIN: { + OutputHandler* tofile = new FileHandler(args->GetTrajectoriesFile().c_str()); + if(_iod) delete _iod; + _iod = new TrajectoriesJPSV06(); + _iod->AddIO(tofile); + //Log->Write("INFO: \tFormat xml-bin not yet supported\n"); + //exit(0); + break; + } + case FORMAT_PLAIN: { + Log->Write("INFO: \tFormat plain not yet supported\n"); + OutputHandler* file = new FileHandler(args->GetTrajectoriesFile().c_str()); + + if(_iod) delete _iod; + _iod = new TrajectoriesFLAT(); + _iod->AddIO(file); + //Log->Write("INFO: \tFormat plain maybe not yet implemented ?"); + //exit(0); + break; + } + case FORMAT_VTK: { + Log->Write("INFO: \tFormat vtk not yet supported\n"); + OutputHandler* file = new FileHandler((args->GetTrajectoriesFile() +".vtk").c_str()); + + if(_iod) delete _iod; + _iod = new TrajectoriesVTK(); + _iod->AddIO(file); + //exit(0); + break; + } + } + + } + + + _distribution = new PedDistributor(args->GetV0Mu(), args->GetV0Sigma(), args->GetBmaxMu(), + args->GetBmaxSigma(), args->GetBminMu(), args->GetBminSigma(), args->GetAtauMu(), + args->GetAtauSigma(), args->GetAminMu(), args->GetAminSigma(), args->GetTauMu(), + args->GetTauSigma()); + s.append(_distribution->writeParameter()); + _distribution->InitDistributor(args->GetProjectFile()); + // define how the navigation line is crossed + int direction = args->GetExitStrategy(); + sprintf(tmp, "\tDirection to the exit: %d\n", direction); + s.append(tmp); + switch (direction) { + case 1: + _direction = new DirectionMiddlePoint(); + break; + case 2: + _direction = new DirectionMinSeperation(); + break; + case 3: + _direction = new DirectionMinSeperationShorterLine(); + break; + case 4: + _direction = new DirectionInRangeBottleneck(); + break; + case 5: + _direction = new DirectionGeneral(); + break; + default: + cout<<"Direction strategy not available. Exit"<<endl; + exit(EXIT_FAILURE); + break; + } + int model = args->GetModel(); + if(model == 1) { //GCFM + _model = new GCFMModel(_direction, args->GetNuPed(), args->GetNuWall(), args->GetDistEffMaxPed(), + args->GetDistEffMaxWall(), args->GetIntPWidthPed(), args->GetIntPWidthWall(), + args->GetMaxFPed(), args->GetMaxFWall()); + s.append("\tModel: GCFMModel\n"); + s.append(_model->writeParameter()); + } else if (model == 2) { //Gompertz + _model = new GompertzModel(_direction, args->GetNuPed(), args->GetNuWall() ); + s.append("\tModel: GompertzModel\n"); + s.append(_model->writeParameter()); + } + // ODE solver + int solver = args->GetSolver(); + sprintf(tmp, "\tODE Loeser: %d\n", solver); + s.append(tmp); + switch (solver) { + case 1: + _solver = new EulerSolverLC(_model); + break; + case 2: + _solver = new VelocityVerletSolver(_model); + break; + case 3: + _solver = new LeapfrogSolver(_model); + break; + } + _tmax = args->GetTmax(); + sprintf(tmp, "\tt_max: %f\n", _tmax); + s.append(tmp); + _deltaT = args->Getdt(); + sprintf(tmp, "\tdt: %f\n", _deltaT); + s.append(tmp); + + _fps=args->Getfps(); + sprintf(tmp, "\tfps: %f\n", _fps); + s.append(tmp); + + // Routing + vector< pair<int, RoutingStrategy> > routers= args->GetRoutingStrategy(); + RoutingEngine* routingEngine= new RoutingEngine(); + + for (unsigned int r= 0; r<routers.size(); r++) { + + RoutingStrategy strategy=routers[r].second; + + int routerID=routers[r].first; + + switch (strategy) { + case ROUTING_LOCAL_SHORTEST: { + Router* router=new GlobalRouter(); + router->SetID(routerID); + router->SetStrategy(strategy); + routingEngine->AddRouter(router); + s.append("\tRouting Strategy local shortest added\n"); + break; + } + case ROUTING_GLOBAL_SHORTEST: { + + Router* router=new GlobalRouter(); + router->SetID(routerID); + router->SetStrategy(strategy); + routingEngine->AddRouter(router); + s.append("\tRouting Strategy global shortest added\n"); + break; + } + case ROUTING_QUICKEST: { + Router* router=new QuickestPathRouter(); + router->SetID(routerID); + router->SetStrategy(strategy); + routingEngine->AddRouter(router); + s.append("\tRouting Strategy quickest path added\n"); + break; + } + case ROUTING_DYNAMIC: { + Router* router=new GraphRouter(); + router->SetID(routerID); + router->SetStrategy(strategy); + routingEngine->AddRouter(router); + s.append("\tRouting Strategy graph router added\n"); + break; + } + case ROUTING_NAV_MESH: { + Router* router=new MeshRouter(); + router->SetID(routerID); + router->SetStrategy(strategy); + routingEngine->AddRouter(router); + s.append("\tRouting Strategy nav_mesh router added\n"); + break; + } + case ROUTING_DUMMY: { + Router* router=new DummyRouter(); + router->SetID(routerID); + router->SetStrategy(strategy); + routingEngine->AddRouter(router); + s.append("\tRouting Strategy dummy router added\n"); + break; + } + case ROUTING_SAFEST: { + Router * router=new SafestPathRouter(); + router->SetID(routerID); + router->SetStrategy(strategy); + routingEngine->AddRouter(router); + s.append("\tRouting Strategy cognitive map router added\n"); + break; + } + case ROUTING_COGNITIVEMAP: { + Router* router=new CognitiveMapRouter(); + router->SetID(routerID); + router->SetStrategy(strategy); + routingEngine->AddRouter(router); + s.append("\tRouting Strategy dummy router added\n"); + break; + } + case ROUTING_UNDEFINED: + default: + cout<<"router not available"<<endl; + exit(EXIT_FAILURE); + break; + } + } + s.append("\n"); + + // IMPORTANT: do not change the order in the following.. + _building = new Building(); + _building->SetRoutingEngine(routingEngine); + _building->SetProjectFilename(args->GetProjectFile()); + _building->SetProjectRootDir(args->GetProjectRootDir()); + + _building->LoadBuildingFromFile(); + _building->LoadRoutingInfo(args->GetProjectFile()); + //_building->AddSurroundingRoom(); + _building->InitGeometry(); // create the polygons + _building->LoadTrafficInfo(); + // in the case the navigation mesh should be written to a file + if(args->GetNavigationMesh()!="") { + Log->Write("INFO: \tWriting the navigation mesh to: " + args->GetNavigationMesh()); + //Navigation mesh implementation + NavMesh* nv= new NavMesh(_building); + nv->BuildNavMesh(); + //nv->WriteToFile("../pedunc/examples/stadium/arena.nav"); + nv->WriteToFile(args->GetNavigationMesh()+".nav"); + nv->WriteToFileTraVisTo(args->GetNavigationMesh()); + //nv->WriteScenario(); + exit(EXIT_FAILURE); + //iod->WriteGeometryRVO(pBuilding);exit(EXIT_FAILURE); + //iod->WriteNavMeshORCA(pBuilding);exit(EXIT_FAILURE); + } + + _nPeds=_distribution->Distribute(_building); + + //using linkedcells + if (args->GetLinkedCells()) { + s.append("\tusing Linked-Cells for spatial queries\n"); + _building->InitGrid(args->GetLinkedCellSize()); + } else { + _building->InitGrid(-1); + } + + // initialize the routing engine before doing any other things + routingEngine->Init(_building); + + //this is very specific to the gcfm model + _building->InitPhiAllPeds(_deltaT); + + + //pBuilding->WriteToErrorLog(); + + //get the seed + _seed=args->GetSeed(); + + // perform a general check to the . + _building->SanityCheck(); + + //read the events + _em = new EventManager(_building); + _em->SetProjectFilename(args->GetProjectFile()); + _em->SetProjectRootDir(args->GetProjectRootDir()); + _em->readEventsXml(); + _em->listEvents(); } -int Simulation::RunSimulation() { - int frameNr = 1; // Frame Number - int writeInterval = (int) ((1. / _fps) / _deltaT + 0.5); - writeInterval = (writeInterval <= 0) ? 1 : writeInterval; // mustn't be <= 0 - double t=0.0; +int Simulation::RunSimulation() +{ + int frameNr = 1; // Frame Number + int writeInterval = (int) ((1. / _fps) / _deltaT + 0.5); + writeInterval = (writeInterval <= 0) ? 1 : writeInterval; // mustn't be <= 0 + double t=0.0; - // writing the header + // writing the header - _iod->WriteHeader(_nPeds, _fps, _building,_seed); - _iod->WriteGeometry(_building); - _iod->WriteFrame(0,_building); + _iod->WriteHeader(_nPeds, _fps, _building,_seed); + _iod->WriteGeometry(_building); + _iod->WriteFrame(0,_building); - //first initialisation needed by the linked-cells - Update(); + //first initialisation needed by the linked-cells + Update(); - // main program loop - for (t = 0; t < _tmax && _nPeds > 0; ++frameNr) { - t = 0 + (frameNr - 1) * _deltaT; - // solve ODE: berechnet Kräfte und setzt neue Werte für x und v - _solver->solveODE(t, t + _deltaT, _building); - // gucken ob Fußgänger in neuen Räumen/Unterräumen - Update(); - _em->Update_Events(t,_deltaT); - // ggf. Ausgabe für TraVisTo - if (frameNr % writeInterval == 0) { - _iod->WriteFrame(frameNr / writeInterval, _building); - } + // main program loop + for (t = 0; t < _tmax && _nPeds > 0; ++frameNr) { + t = 0 + (frameNr - 1) * _deltaT; + // solve ODE: berechnet Kräfte und setzt neue Werte für x und v + _solver->solveODE(t, t + _deltaT, _building); + // gucken ob Fußgänger in neuen Räumen/Unterräumen + Update(); + _em->Update_Events(t,_deltaT); + // ggf. Ausgabe für TraVisTo + if (frameNr % writeInterval == 0) { + _iod->WriteFrame(frameNr / writeInterval, _building); + } - } - // writing the footer - _iod->WriteFooter(); + } + // writing the footer + _iod->WriteFooter(); - if(_argsParser->GetFileFormat()==FORMAT_XML_BIN){ + if(_argsParser->GetFileFormat()==FORMAT_XML_BIN) { - delete _iod; - _iod=NULL; + delete _iod; + _iod=NULL; // char tmp[CLENGTH]; // int f= frameNr / writeInterval ; // sprintf(tmp,"<frameCount>%07d</frameCount>",f); // string frameCount (tmp); - char replace[CLENGTH]; - // open the file and replace the 8th line - sprintf(replace,"sed -i '9s/.*/ %d /' %s", frameNr/ writeInterval, _argsParser->GetTrajectoriesFile().c_str()); - //sprintf(replace,"sed -i '8s#.*#<%s>#' %s", "glas", _argsParser->GetTrajectoriesFile().c_str()); - //sprintf(replace,"sed -i '8s#.*#%s#' %s", "\\<te\\>", _argsParser->GetTrajectoriesFile().c_str()); + char replace[CLENGTH]; + // open the file and replace the 8th line + sprintf(replace,"sed -i '9s/.*/ %d /' %s", frameNr/ writeInterval, _argsParser->GetTrajectoriesFile().c_str()); + //sprintf(replace,"sed -i '8s#.*#<%s>#' %s", "glas", _argsParser->GetTrajectoriesFile().c_str()); + //sprintf(replace,"sed -i '8s#.*#%s#' %s", "\\<te\\>", _argsParser->GetTrajectoriesFile().c_str()); - system(replace); - } + system(replace); + } - //return the evacuation time - return (int) t; + //return the evacuation time + return (int) t; } // TODO: make the building class more independent by moving the update routing here. -void Simulation::Update() { - //_building->Update(); - _building->UpdateVerySlow(); - //someone might have leave the building - _nPeds=_building->GetAllPedestrians().size(); - // update the global time - Pedestrian::SetGlobalTime(Pedestrian::GetGlobalTime()+_deltaT); - //update the cells position - _building->UpdateGrid(); +void Simulation::Update() +{ + //_building->Update(); + _building->UpdateVerySlow(); + //someone might have leave the building + _nPeds=_building->GetAllPedestrians().size(); + // update the global time + Pedestrian::SetGlobalTime(Pedestrian::GetGlobalTime()+_deltaT); + //update the cells position + _building->UpdateGrid(); } -void Simulation::PrintStatistics() { - Log->Write("\nEXIT USAGE:"); - const map<int, Transition*>& transitions = _building->GetAllTransitions(); - map<int, Transition*>::const_iterator itr; - for(itr = transitions.begin(); itr != transitions.end(); ++itr){ - Transition* goal = itr->second; - if(goal->IsExit()){ - Log->Write("Exit ID [%d] used by [%d] pedestrians. Last passing time [%0.2f] s",goal->GetID(),goal->GetDoorUsage(),goal->GetLastPassingTime()); - } - } +void Simulation::PrintStatistics() +{ + Log->Write("\nEXIT USAGE:"); + const map<int, Transition*>& transitions = _building->GetAllTransitions(); + map<int, Transition*>::const_iterator itr; + for(itr = transitions.begin(); itr != transitions.end(); ++itr) { + Transition* goal = itr->second; + if(goal->IsExit()) { + Log->Write("Exit ID [%d] used by [%d] pedestrians. Last passing time [%0.2f] s",goal->GetID(),goal->GetDoorUsage(),goal->GetLastPassingTime()); + } + } } diff --git a/Simulation.h b/Simulation.h index 4a9287471d94d8b0c11732d6589f66b902ead051..b093853b7897ef428a9818dbf3a71cfad8c30728 100644 --- a/Simulation.h +++ b/Simulation.h @@ -51,81 +51,81 @@ extern OutputHandler* Log; class Simulation { - private: - ///Number of pedestrians in the simulation - int _nPeds; - ///Maximum simulation time - double _tmax; - /// time step - double _deltaT; - /// frame rate for the trajectories - double _fps; - ///seed using for the random number generator - unsigned int _seed; - /// building object - Building* _building; - ///initial distribution of the pedestrians - PedDistributor* _distribution; - /// door crossing strategy for the pedestrians - DirectionStrategy* _direction; - /// Force model to use - ForceModel* _model; - /// differential equation solver - ODESolver* _solver; - /// writing the trajectories to file - IODispatcher* _iod; - ///new: EventManager - EventManager* _em; - /// argument parser - ArgumentParser* _argsParser; - - - public: - Simulation(); - virtual ~Simulation(); - - /** - * Initialize the number of agents in the simulation - */ - void SetPedsNumber(int i); - - /** - * Initialize the number of agents in the simulation - */ - int GetPedsNumber() const; - - /** - * Returns the number of agents when running on a distributed system (MPI) - * NOT IMPLEMENTED - */ - int GetNPedsGlobal() const; - - /** - * @return the building object containing all geometry elements - */ - Building* GetBuilding() const; - - /** - * Read parameters from the argument parser class. - */ - void InitArgs(ArgumentParser *args); - - /** - * - * @return the total simulated/evacuation time - */ - int RunSimulation(); - - /** - * Update the pedestrians states: positions, velocity, route - */ - void Update(); - - - /** - * print some statistics about the simulation - */ - void PrintStatistics(); +private: + ///Number of pedestrians in the simulation + int _nPeds; + ///Maximum simulation time + double _tmax; + /// time step + double _deltaT; + /// frame rate for the trajectories + double _fps; + ///seed using for the random number generator + unsigned int _seed; + /// building object + Building* _building; + ///initial distribution of the pedestrians + PedDistributor* _distribution; + /// door crossing strategy for the pedestrians + DirectionStrategy* _direction; + /// Force model to use + ForceModel* _model; + /// differential equation solver + ODESolver* _solver; + /// writing the trajectories to file + IODispatcher* _iod; + ///new: EventManager + EventManager* _em; + /// argument parser + ArgumentParser* _argsParser; + + +public: + Simulation(); + virtual ~Simulation(); + + /** + * Initialize the number of agents in the simulation + */ + void SetPedsNumber(int i); + + /** + * Initialize the number of agents in the simulation + */ + int GetPedsNumber() const; + + /** + * Returns the number of agents when running on a distributed system (MPI) + * NOT IMPLEMENTED + */ + int GetNPedsGlobal() const; + + /** + * @return the building object containing all geometry elements + */ + Building* GetBuilding() const; + + /** + * Read parameters from the argument parser class. + */ + void InitArgs(ArgumentParser *args); + + /** + * + * @return the total simulated/evacuation time + */ + int RunSimulation(); + + /** + * Update the pedestrians states: positions, velocity, route + */ + void Update(); + + + /** + * print some statistics about the simulation + */ + void PrintStatistics(); }; diff --git a/Utest/testClassLine.cpp b/Utest/testClassLine.cpp index f4e036cf4028cbbf9461c5d135a477508a6f96fb..b8495835bd37a2e4cd0d0f27ae001a9e728746f3 100644 --- a/Utest/testClassLine.cpp +++ b/Utest/testClassLine.cpp @@ -5,11 +5,11 @@ #ifdef WINDOWS #include <direct.h> - #define GetCurrentDir _getcwd +#define GetCurrentDir _getcwd #else #include <unistd.h> - #define GetCurrentDir getcwd - #endif +#define GetCurrentDir getcwd +#endif const double eps = 0.00001; const double pi= atan(1)*4; @@ -17,269 +17,267 @@ const double pi= atan(1)*4; int testIntersectionWith(FILE * f) { - fprintf (f, "\t+++++ Enter testIntersectionWith() +++++\n"); - int ntests=8, - res=0; - - bool bres; + fprintf (f, "\t+++++ Enter testIntersectionWith() +++++\n"); + int ntests=8, + res=0; - Line L1 = Line( Point(1, 1), Point(2, 3)); - Line L2 = Line( Point(1, 0), Point(0, 1));//no - Line L3 = Line( Point(2, 0), Point(0, 2));//touche - Line L4 = Line( Point(3, 0), Point(0, 3));//inter - Line L5 = Line( Point(4, 0), Point(0, 4));//inter - Line L6 = Line( Point(5, 0), Point(0, 5));//touche - Line L7 = Line( Point(6, 0), Point(0, 6));//no - Line L8 = Line( Point(2, 1), Point(3, 3));//parallel - Line L9 = Line( Point(2, -1), Point(3, -2));//parallel - bres = L1.IntersectionWith(L2); - if (!bres) - res++; - fprintf (f, "%2d. res=%2d, L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", ntests, res, L1.GetPoint1().GetX(),L1.GetPoint1().GetY(),L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), L2.GetPoint1().GetX(),L2.GetPoint1().GetY(),L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); + bool bres; + + Line L1 = Line( Point(1, 1), Point(2, 3)); + Line L2 = Line( Point(1, 0), Point(0, 1));//no + Line L3 = Line( Point(2, 0), Point(0, 2));//touche + Line L4 = Line( Point(3, 0), Point(0, 3));//inter + Line L5 = Line( Point(4, 0), Point(0, 4));//inter + Line L6 = Line( Point(5, 0), Point(0, 5));//touche + Line L7 = Line( Point(6, 0), Point(0, 6));//no + Line L8 = Line( Point(2, 1), Point(3, 3));//parallel + Line L9 = Line( Point(2, -1), Point(3, -2));//parallel + bres = L1.IntersectionWith(L2); + if (!bres) + res++; + fprintf (f, "%2d. res=%2d, L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", ntests, res, L1.GetPoint1().GetX(),L1.GetPoint1().GetY(),L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), L2.GetPoint1().GetX(),L2.GetPoint1().GetY(),L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); //////////////////////////////////////////////// - L2=L3; - bres = L1.IntersectionWith(L2); - if (bres) - res++; - fprintf (f, "%2d. res=%2d, L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", ntests, res, L1.GetPoint1().GetX(),L1.GetPoint1().GetY(),L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), L2.GetPoint1().GetX(),L2.GetPoint1().GetY(),L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); + L2=L3; + bres = L1.IntersectionWith(L2); + if (bres) + res++; + fprintf (f, "%2d. res=%2d, L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", ntests, res, L1.GetPoint1().GetX(),L1.GetPoint1().GetY(),L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), L2.GetPoint1().GetX(),L2.GetPoint1().GetY(),L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); //////////////////////////////////////////////// - L2=L4; - bres = L1.IntersectionWith(L2); - if (bres) - res++; - fprintf (f, "%2d. res=%2d, L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", ntests, res, L1.GetPoint1().GetX(),L1.GetPoint1().GetY(),L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), L2.GetPoint1().GetX(),L2.GetPoint1().GetY(),L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); + L2=L4; + bres = L1.IntersectionWith(L2); + if (bres) + res++; + fprintf (f, "%2d. res=%2d, L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", ntests, res, L1.GetPoint1().GetX(),L1.GetPoint1().GetY(),L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), L2.GetPoint1().GetX(),L2.GetPoint1().GetY(),L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); //////////////////////////////////////////////// - L2=L5; - bres = L1.IntersectionWith(L2); - if (bres) - res++; - fprintf (f, "%2d. res=%2d, L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", ntests, res, L1.GetPoint1().GetX(),L1.GetPoint1().GetY(),L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), L2.GetPoint1().GetX(),L2.GetPoint1().GetY(),L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); + L2=L5; + bres = L1.IntersectionWith(L2); + if (bres) + res++; + fprintf (f, "%2d. res=%2d, L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", ntests, res, L1.GetPoint1().GetX(),L1.GetPoint1().GetY(),L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), L2.GetPoint1().GetX(),L2.GetPoint1().GetY(),L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); //////////////////////////////////////////////// - L2=L6; - bres = L1.IntersectionWith(L2); - if (bres) - res++; - fprintf (f, "%2d. res=%2d, L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", ntests, res, L1.GetPoint1().GetX(),L1.GetPoint1().GetY(),L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), L2.GetPoint1().GetX(),L2.GetPoint1().GetY(),L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); + L2=L6; + bres = L1.IntersectionWith(L2); + if (bres) + res++; + fprintf (f, "%2d. res=%2d, L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", ntests, res, L1.GetPoint1().GetX(),L1.GetPoint1().GetY(),L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), L2.GetPoint1().GetX(),L2.GetPoint1().GetY(),L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); //////////////////////////////////////////////// - L2=L7; - bres = L1.IntersectionWith(L2); - if (!bres) - res++; - fprintf (f, "%2d. res=%2d, L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", ntests, res, L1.GetPoint1().GetX(),L1.GetPoint1().GetY(),L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), L2.GetPoint1().GetX(),L2.GetPoint1().GetY(),L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); - + L2=L7; + bres = L1.IntersectionWith(L2); + if (!bres) + res++; + fprintf (f, "%2d. res=%2d, L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", ntests, res, L1.GetPoint1().GetX(),L1.GetPoint1().GetY(),L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), L2.GetPoint1().GetX(),L2.GetPoint1().GetY(),L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); + //////////////////////////////////////////////// - L2=L8; - bres = L1.IntersectionWith(L2); - if (!bres) - res++; - fprintf (f, "%2d. res=%2d, L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", ntests, res, L1.GetPoint1().GetX(),L1.GetPoint1().GetY(),L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), L2.GetPoint1().GetX(),L2.GetPoint1().GetY(),L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); + L2=L8; + bres = L1.IntersectionWith(L2); + if (!bres) + res++; + fprintf (f, "%2d. res=%2d, L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", ntests, res, L1.GetPoint1().GetX(),L1.GetPoint1().GetY(),L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), L2.GetPoint1().GetX(),L2.GetPoint1().GetY(),L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); //////////////////////////////////////////////// - L1=L2; - L2=L9; - bres = L1.IntersectionWith(L2); - if (!bres) - res++; - fprintf (f, "%2d. res=%2d, L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", ntests, res, L1.GetPoint1().GetX(),L1.GetPoint1().GetY(),L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), L2.GetPoint1().GetX(),L2.GetPoint1().GetY(),L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); + L1=L2; + L2=L9; + bres = L1.IntersectionWith(L2); + if (!bres) + res++; + fprintf (f, "%2d. res=%2d, L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", ntests, res, L1.GetPoint1().GetX(),L1.GetPoint1().GetY(),L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), L2.GetPoint1().GetX(),L2.GetPoint1().GetY(),L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); //////////////////////////////////////////////// - fprintf (f, "\t+++++ Leave testIntersectionWith() +++++\n\n"); - return (res==ntests)?1:0; + fprintf (f, "\t+++++ Leave testIntersectionWith() +++++\n\n"); + return (res==ntests)?1:0; } int testGetAngle(FILE * f) { - fprintf (f, "\t+++++ Enter testGetAngle() +++++\n"); - int ntests=9, - res=0; - double angle; - Line L1 = Line( Point(1, 2), Point(3, 4)); - Line L2 = Line( Point(0, 3), Point(3, 3)); - angle = L1.GetAngle(L2); - if ( fabs(pi/4 + angle)< 0.001) - res++; - fprintf (f, "%2d. res=%2d, A=%.2f | \ + fprintf (f, "\t+++++ Enter testGetAngle() +++++\n"); + int ntests=9, + res=0; + double angle; + Line L1 = Line( Point(1, 2), Point(3, 4)); + Line L2 = Line( Point(0, 3), Point(3, 3)); + angle = L1.GetAngle(L2); + if ( fabs(pi/4 + angle)< 0.001) + res++; + fprintf (f, "%2d. res=%2d, A=%.2f | \ L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), \ L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", \ - ntests, res, angle*180/pi, \ - L1.GetPoint1().GetX(),L1.GetPoint1().GetY(), \ - L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), \ - L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ - L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); + ntests, res, angle*180/pi, \ + L1.GetPoint1().GetX(),L1.GetPoint1().GetY(), \ + L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), \ + L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ + L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); //////////////////////////////////////////////// - L1 = Line( Point(3, 4), Point(1, 2)); - angle = L1.GetAngle(L2); - if (fabs(pi/4 + angle)< 0.001) - res++; - fprintf (f, "%2d. res=%2d, A=%.2f | \ + L1 = Line( Point(3, 4), Point(1, 2)); + angle = L1.GetAngle(L2); + if (fabs(pi/4 + angle)< 0.001) + res++; + fprintf (f, "%2d. res=%2d, A=%.2f | \ L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), \ L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", \ - ntests, res, angle*180/pi, \ - L1.GetPoint1().GetX(),L1.GetPoint1().GetY(), \ - L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), \ - L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ - L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); + ntests, res, angle*180/pi, \ + L1.GetPoint1().GetX(),L1.GetPoint1().GetY(), \ + L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), \ + L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ + L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); //////////////////////////////////////////////// - L1 = Line( Point(1, 4), Point(3, 2)); - angle = L1.GetAngle(L2); - if (fabs(angle - pi/4)< 0.001) - res++; - fprintf (f, "%2d. res=%2d, A=%.2f | \ + L1 = Line( Point(1, 4), Point(3, 2)); + angle = L1.GetAngle(L2); + if (fabs(angle - pi/4)< 0.001) + res++; + fprintf (f, "%2d. res=%2d, A=%.2f | \ L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), \ L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", \ - ntests, res, angle*180/pi, \ - L1.GetPoint1().GetX(),L1.GetPoint1().GetY(), \ - L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), \ - L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ - L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); + ntests, res, angle*180/pi, \ + L1.GetPoint1().GetX(),L1.GetPoint1().GetY(), \ + L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), \ + L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ + L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); //////////////////////////////////////////////// - L1 = Line( Point(3, 2), Point(1, 4)); - angle = L1.GetAngle(L2); - if (fabs(angle-pi/4)< 0.001) - res++; - fprintf (f, "%2d. res=%2d, A=%.2f | \ + L1 = Line( Point(3, 2), Point(1, 4)); + angle = L1.GetAngle(L2); + if (fabs(angle-pi/4)< 0.001) + res++; + fprintf (f, "%2d. res=%2d, A=%.2f | \ L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), \ L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", \ - ntests, res, angle*180/pi, \ - L1.GetPoint1().GetX(),L1.GetPoint1().GetY(), \ - L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), \ - L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ - L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); - + ntests, res, angle*180/pi, \ + L1.GetPoint1().GetX(),L1.GetPoint1().GetY(), \ + L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), \ + L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ + L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); + //////////////////////////////////////////////// - L2 = Line( Point(3, 3), Point(0, 3)); - angle = L1.GetAngle(L2); - if (fabs(angle-pi/4)< 0.001) - res++; - fprintf (f, "%2d. res=%2d, A=%.2f | \ + L2 = Line( Point(3, 3), Point(0, 3)); + angle = L1.GetAngle(L2); + if (fabs(angle-pi/4)< 0.001) + res++; + fprintf (f, "%2d. res=%2d, A=%.2f | \ L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), \ L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", \ - ntests, res, angle*180/pi, \ - L1.GetPoint1().GetX(),L1.GetPoint1().GetY(), \ - L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), \ - L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ - L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); + ntests, res, angle*180/pi, \ + L1.GetPoint1().GetX(),L1.GetPoint1().GetY(), \ + L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), \ + L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ + L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); //////////////////////////////////////////////// - L2 = Line( Point(1, 1), Point(3, 3)); - L1 = Line( Point(3, 2), Point(0, 2)); - angle = L1.GetAngle(L2); - if (fabs(angle-pi/4)< 0.001) - res++; - fprintf (f, "%2d. res=%2d, A=%.2f | \ + L2 = Line( Point(1, 1), Point(3, 3)); + L1 = Line( Point(3, 2), Point(0, 2)); + angle = L1.GetAngle(L2); + if (fabs(angle-pi/4)< 0.001) + res++; + fprintf (f, "%2d. res=%2d, A=%.2f | \ L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), \ L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", \ - ntests, res, angle*180/pi, \ - L1.GetPoint1().GetX(),L1.GetPoint1().GetY(), \ - L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), \ - L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ - L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); - + ntests, res, angle*180/pi, \ + L1.GetPoint1().GetX(),L1.GetPoint1().GetY(), \ + L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), \ + L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ + L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); + //////////////////////////////////////////////// - L2 = Line( Point(3, 3), Point(1, 1) ); - L1 = Line( Point(3, 2), Point(0, 2)); - angle = L1.GetAngle(L2); - if (fabs(angle-pi/4)< 0.001) - res++; - fprintf (f, "%2d. res=%2d, A=%.2f | \ + L2 = Line( Point(3, 3), Point(1, 1) ); + L1 = Line( Point(3, 2), Point(0, 2)); + angle = L1.GetAngle(L2); + if (fabs(angle-pi/4)< 0.001) + res++; + fprintf (f, "%2d. res=%2d, A=%.2f | \ L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), \ L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", \ - ntests, res, angle*180/pi, \ - L1.GetPoint1().GetX(),L1.GetPoint1().GetY(), \ - L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), \ - L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ - L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); - + ntests, res, angle*180/pi, \ + L1.GetPoint1().GetX(),L1.GetPoint1().GetY(), \ + L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), \ + L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ + L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); + //////////////////////////////////////////////// - L2 = Line( Point(6, 5), Point(10, 7) ); - L1 = Line( Point(6,5), Point(7.4, 9.28)); - angle = L1.GetAngle(L2); - if (fabs(angle+pi/4)< 1) - res++; - fprintf (f, "%2d. res=%2d, A=%.2f | \ + L2 = Line( Point(6, 5), Point(10, 7) ); + L1 = Line( Point(6,5), Point(7.4, 9.28)); + angle = L1.GetAngle(L2); + if (fabs(angle+pi/4)< 1) + res++; + fprintf (f, "%2d. res=%2d, A=%.2f | \ L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), \ L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", \ - ntests, res, angle*180/pi, \ - L1.GetPoint1().GetX(),L1.GetPoint1().GetY(), \ - L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), \ - L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ - L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); + ntests, res, angle*180/pi, \ + L1.GetPoint1().GetX(),L1.GetPoint1().GetY(), \ + L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), \ + L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ + L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); //////////////////////////////////////////////// - L1 = Line( Point(8.0467, 6.9756), Point(10.08, 2.9578) ); - L2 = Line( Point(8.0467, 6.9756), Point(6.63, 2.733)); - angle = L1.GetAngle(L2); - if (fabs(angle+pi/4)< 1) - res++; - fprintf (f, "%2d. res=%2d, A=%.2f | \ + L1 = Line( Point(8.0467, 6.9756), Point(10.08, 2.9578) ); + L2 = Line( Point(8.0467, 6.9756), Point(6.63, 2.733)); + angle = L1.GetAngle(L2); + if (fabs(angle+pi/4)< 1) + res++; + fprintf (f, "%2d. res=%2d, A=%.2f | \ L1_P1(%.2f, %.2f), L1_P2(%.2f, %.2f), \ L2_P1(%.2f, %.2f) L2_P2(%.2f, %.2f)\n", \ - ntests, res, angle*180/pi, \ - L1.GetPoint1().GetX(),L1.GetPoint1().GetY(), \ - L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), \ - L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ - L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); + ntests, res, angle*180/pi, \ + L1.GetPoint1().GetX(),L1.GetPoint1().GetY(), \ + L1.GetPoint2().GetX(),L1.GetPoint2().GetY(), \ + L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ + L2.GetPoint2().GetX(),L2.GetPoint2().GetY()); + + int i; + double phi=0, imax = 10; //rotation angle for tests + Line L3; //the rotation of L1 + L2 = Line( Point(0, 0), Point( 3, 0)); + L1 = Line( Point(0, 0), Point(5, 0) ); + Point P1, P2; - int i; - double phi=0, imax = 10; //rotation angle for tests - Line L3; //the rotation of L1 - L2 = Line( Point(0, 0), Point( 3, 0)); - L1 = Line( Point(0, 0), Point(5, 0) ); - Point P1, P2; + for (i=1; i<= imax; i++) { + L3 = L1; + phi += pi/imax; + P1 = L1.GetPoint2().Rotate(cos(phi), sin(phi)) ; + L3.SetPoint2( P1 ); + angle = L3.GetAngle(L2); + P2 = P1.Rotate(cos(angle), sin(angle)) ; - for (i=1; i<= imax; i++) - { - L3 = L1; - phi += pi/imax; - P1 = L1.GetPoint2().Rotate(cos(phi), sin(phi)) ; - L3.SetPoint2( P1 ); - angle = L3.GetAngle(L2); - P2 = P1.Rotate(cos(angle), sin(angle)) ; - -// angle L1_P1 L1_P2 L2_P1 L2_P2 L3_P1 L3_P2 - fprintf (stderr, "%f %f\t %.2f %.2f %.2f %.2f \t %.2f %.2f %.2f %.2f\t %.2f %.2f %.2f %.2f\n", \ - phi, angle, \ - L3.GetPoint1().GetX(),L3.GetPoint1().GetY(), \ - P1.GetX(), P1.GetY(), \ - L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ - L2.GetPoint2().GetX(),L2.GetPoint2().GetY(), \ - L3.GetPoint1().GetX(),L3.GetPoint1().GetY(), \ - P2.GetX(), P2.GetY()); - } +// angle L1_P1 L1_P2 L2_P1 L2_P2 L3_P1 L3_P2 + fprintf (stderr, "%f %f\t %.2f %.2f %.2f %.2f \t %.2f %.2f %.2f %.2f\t %.2f %.2f %.2f %.2f\n", \ + phi, angle, \ + L3.GetPoint1().GetX(),L3.GetPoint1().GetY(), \ + P1.GetX(), P1.GetY(), \ + L2.GetPoint1().GetX(),L2.GetPoint1().GetY(), \ + L2.GetPoint2().GetX(),L2.GetPoint2().GetY(), \ + L3.GetPoint1().GetX(),L3.GetPoint1().GetY(), \ + P2.GetX(), P2.GetY()); + } //////////////////////////////////////////////// - fprintf (f, "\t+++++ Leave testGetAngle() +++++\n\n"); - return (res==ntests)?1:0; + fprintf (f, "\t+++++ Leave testGetAngle() +++++\n\n"); + return (res==ntests)?1:0; } int main() { - FILE * f; - char fname[FILENAME_MAX] = "log_testClassLine.txt"; - char cCurrentPath[FILENAME_MAX]; - f = fopen(fname, "w"); - if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) - { - return EXIT_FAILURE; - } - cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ + FILE * f; + char fname[FILENAME_MAX] = "log_testClassLine.txt"; + char cCurrentPath[FILENAME_MAX]; + f = fopen(fname, "w"); + if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) { + return EXIT_FAILURE; + } + cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ + + fprintf (f, "The current working directory is %s\n\n", cCurrentPath); - fprintf (f, "The current working directory is %s\n\n", cCurrentPath); + int res = 0, ntests = 0; - int res = 0, ntests = 0; + res += testIntersectionWith(f); + ntests++; - res += testIntersectionWith(f); - ntests++; + res += testGetAngle(f); + ntests++; - res += testGetAngle(f); - ntests++; - - fclose(f); - return (res==ntests)?EXIT_SUCCESS:EXIT_FAILURE; + fclose(f); + return (res==ntests)?EXIT_SUCCESS:EXIT_FAILURE; } diff --git a/Utest/testClassPoint.cpp b/Utest/testClassPoint.cpp index d1f7d7022439ea2155e7e43d8ae8d877fbf2d869..319ca3504e3c8a0474e0d740335ef2cbb67536bf 100644 --- a/Utest/testClassPoint.cpp +++ b/Utest/testClassPoint.cpp @@ -6,421 +6,459 @@ #ifdef WINDOWS #include <direct.h> - #define GetCurrentDir _getcwd +#define GetCurrentDir _getcwd #else #include <unistd.h> - #define GetCurrentDir getcwd - #endif +#define GetCurrentDir getcwd +#endif const double eps = 0.00001; const double pi= atan(1)*4; int testNorm(FILE * f) { - fprintf (f, "\t+++++ Enter testNorm() +++++\n"); - int ntests=0, res=0; - Point P(0,0); //test point - double pnorm, expected, px, py; - //------------------------------------------------------------------------------ - pnorm = P.Norm(); - expected = 0; - res += ( pnorm == expected )?1:0; - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), norm=%.2f\n", ntests, res, P._x, P._y, pnorm); - //------------------------------------------------------------------------------ - px = 1; py = 0; P.SetX(px); P.SetY(py); pnorm = P.Norm(); expected = 1; - res += ( pnorm == expected )?1:0; - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), norm=%.2f\n",ntests, res, P._x, P._y, pnorm); - //------------------------------------------------------------------------------ - px = -1; py = 0; P.SetX(px); P.SetY(py); pnorm = P.Norm(); expected = 1; - res += ( pnorm == expected )?1:0; - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), norm=%.2f\n",ntests, res, P._x, P._y, pnorm); - //------------------------------------------------------------------------------ - px = 0; py = 1; P.SetX(px); P.SetY(py); pnorm = P.Norm(); expected = 1; - res += ( pnorm == expected )?1:0; - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), norm=%.2f\n",ntests, res, P._x, P._y, pnorm); - //------------------------------------------------------------------------------ - px = 0; py = -1; P.SetX(px); P.SetY(py); pnorm = P.Norm(); expected = 1; - res += ( pnorm == expected )?1:0; - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), norm=%.2f\n",ntests, res, P._x, P._y, pnorm); - //------------------------------------------------------------------------------ - px = 1; py = 1; P.SetX(px); P.SetY(py); pnorm = P.Norm(); expected = sqrt(2); - res += ( pnorm == expected )?1:0; - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), norm=%.2f\n",ntests, res, P._x, P._y, pnorm); - //------------------------------------------------------------------------------ - px = 3; py = 0; P.SetX(px); P.SetY(py); pnorm = P.Norm(); expected = 3; - res += ( pnorm == expected )?1:0; - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), norm=%.2f\n",ntests, res, P._x, P._y, pnorm); - //------------------------------------------------------------------------------ - px = 0; py = -3; P.SetX(px); P.SetY(py); pnorm = P.Norm(); expected = 3; - res += ( pnorm == expected )?1:0; - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), norm=%.2f\n",ntests, res, P._x, P._y, pnorm); - //------------------------------------------------------------------------------- - fprintf (f, "\t+++++ Leave testNorm() +++++\n\n"); - return (res==ntests)?1:0; + fprintf (f, "\t+++++ Enter testNorm() +++++\n"); + int ntests=0, res=0; + Point P(0,0); //test point + double pnorm, expected, px, py; + //------------------------------------------------------------------------------ + pnorm = P.Norm(); + expected = 0; + res += ( pnorm == expected )?1:0; + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), norm=%.2f\n", ntests, res, P._x, P._y, pnorm); + //------------------------------------------------------------------------------ + px = 1; + py = 0; + P.SetX(px); + P.SetY(py); + pnorm = P.Norm(); + expected = 1; + res += ( pnorm == expected )?1:0; + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), norm=%.2f\n",ntests, res, P._x, P._y, pnorm); + //------------------------------------------------------------------------------ + px = -1; + py = 0; + P.SetX(px); + P.SetY(py); + pnorm = P.Norm(); + expected = 1; + res += ( pnorm == expected )?1:0; + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), norm=%.2f\n",ntests, res, P._x, P._y, pnorm); + //------------------------------------------------------------------------------ + px = 0; + py = 1; + P.SetX(px); + P.SetY(py); + pnorm = P.Norm(); + expected = 1; + res += ( pnorm == expected )?1:0; + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), norm=%.2f\n",ntests, res, P._x, P._y, pnorm); + //------------------------------------------------------------------------------ + px = 0; + py = -1; + P.SetX(px); + P.SetY(py); + pnorm = P.Norm(); + expected = 1; + res += ( pnorm == expected )?1:0; + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), norm=%.2f\n",ntests, res, P._x, P._y, pnorm); + //------------------------------------------------------------------------------ + px = 1; + py = 1; + P.SetX(px); + P.SetY(py); + pnorm = P.Norm(); + expected = sqrt(2); + res += ( pnorm == expected )?1:0; + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), norm=%.2f\n",ntests, res, P._x, P._y, pnorm); + //------------------------------------------------------------------------------ + px = 3; + py = 0; + P.SetX(px); + P.SetY(py); + pnorm = P.Norm(); + expected = 3; + res += ( pnorm == expected )?1:0; + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), norm=%.2f\n",ntests, res, P._x, P._y, pnorm); + //------------------------------------------------------------------------------ + px = 0; + py = -3; + P.SetX(px); + P.SetY(py); + pnorm = P.Norm(); + expected = 3; + res += ( pnorm == expected )?1:0; + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), norm=%.2f\n",ntests, res, P._x, P._y, pnorm); + //------------------------------------------------------------------------------- + fprintf (f, "\t+++++ Leave testNorm() +++++\n\n"); + return (res==ntests)?1:0; } int testNormalized(FILE * f) { - fprintf (f, "\t+++++ Enter testNormalized() +++++\n"); - int ntests=0, res=0; - Point P(0,0), nP(0,0), eP(0,0); - //----------------------------------------------------------------------------- - nP = P.Normalized(); eP._x = 0; eP._y = 0; - res += ( nP == eP )?1:0; - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), nP(%.2f, %.2f), eP(%.2f, %.2f)\n", ntests, res, P._x, P._y, nP._x, nP._y, eP._x, eP._y ); - //------------------------------------------------------------------------------ - P._x = -0.5; P._y = 0; nP = P.Normalized(); eP._x = -1; eP._y = 0; - res += ( nP == eP )?1:0; - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), nP(%.2f, %.2f), eP(%.2f, %.2f)\n", ntests, res, P._x, P._y, nP._x, nP._y, eP._x, eP._y ); - //------------------------------------------------------------------------------ - P._x = 0; P._y = -0.5; nP = P.Normalized(); eP._x = 0; eP._y = -1; - res += ( nP == eP )?1:0; - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), nP(%.2f, %.2f), eP(%.2f, %.2f)\n", ntests, res, P._x, P._y, nP._x, nP._y, eP._x, eP._y ); - //------------------------------------------------------------------------------ - P._x = -0.5; P._y = 0.5; nP = P.Normalized(); eP._x = -1./sqrt(2); eP._y = -eP._x; - res += ( nP == eP )?1:0; - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), nP(%.2f, %.2f), eP(%.2f, %.2f)\n", ntests, res, P._x, P._y, nP._x, nP._y, eP._x, eP._y ); - //------------------------------------------------------------------------------ - P._x = 1000.432; P._y = 0; nP = P.Normalized(); eP._x = 1; eP._y = 0; - res += ( nP == eP )?1:0; - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), nP(%.2f, %.2f), eP(%.2f, %.2f)\n", ntests, res, P._x, P._y, nP._x, nP._y, eP._x, eP._y ); - //------------------------------------------------------------------------------ - P._x = 0; P._y = -12345.789; nP = P.Normalized(); eP._x = 0; eP._y = -1; - res += ( nP == eP )?1:0; - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), nP(%.2f, %.2f), eP(%.2f, %.2f)\n", ntests, res, P._x, P._y, nP._x, nP._y, eP._x, eP._y ); - //------------------------------------------------------------------------------ - fprintf (f, "\t+++++ Leave testNormalized() +++++\n\n"); - return (res==ntests)?1:0; + fprintf (f, "\t+++++ Enter testNormalized() +++++\n"); + int ntests=0, res=0; + Point P(0,0), nP(0,0), eP(0,0); + //----------------------------------------------------------------------------- + nP = P.Normalized(); + eP._x = 0; + eP._y = 0; + res += ( nP == eP )?1:0; + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), nP(%.2f, %.2f), eP(%.2f, %.2f)\n", ntests, res, P._x, P._y, nP._x, nP._y, eP._x, eP._y ); + //------------------------------------------------------------------------------ + P._x = -0.5; + P._y = 0; + nP = P.Normalized(); + eP._x = -1; + eP._y = 0; + res += ( nP == eP )?1:0; + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), nP(%.2f, %.2f), eP(%.2f, %.2f)\n", ntests, res, P._x, P._y, nP._x, nP._y, eP._x, eP._y ); + //------------------------------------------------------------------------------ + P._x = 0; + P._y = -0.5; + nP = P.Normalized(); + eP._x = 0; + eP._y = -1; + res += ( nP == eP )?1:0; + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), nP(%.2f, %.2f), eP(%.2f, %.2f)\n", ntests, res, P._x, P._y, nP._x, nP._y, eP._x, eP._y ); + //------------------------------------------------------------------------------ + P._x = -0.5; + P._y = 0.5; + nP = P.Normalized(); + eP._x = -1./sqrt(2); + eP._y = -eP._x; + res += ( nP == eP )?1:0; + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), nP(%.2f, %.2f), eP(%.2f, %.2f)\n", ntests, res, P._x, P._y, nP._x, nP._y, eP._x, eP._y ); + //------------------------------------------------------------------------------ + P._x = 1000.432; + P._y = 0; + nP = P.Normalized(); + eP._x = 1; + eP._y = 0; + res += ( nP == eP )?1:0; + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), nP(%.2f, %.2f), eP(%.2f, %.2f)\n", ntests, res, P._x, P._y, nP._x, nP._y, eP._x, eP._y ); + //------------------------------------------------------------------------------ + P._x = 0; + P._y = -12345.789; + nP = P.Normalized(); + eP._x = 0; + eP._y = -1; + res += ( nP == eP )?1:0; + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), nP(%.2f, %.2f), eP(%.2f, %.2f)\n", ntests, res, P._x, P._y, nP._x, nP._y, eP._x, eP._y ); + //------------------------------------------------------------------------------ + fprintf (f, "\t+++++ Leave testNormalized() +++++\n\n"); + return (res==ntests)?1:0; } int testScalarP(FILE * f) { - fprintf (f, "\t+++++ Enter testScalarP() +++++\n"); - Point Points[] = - { - Point(1, 2), - Point(0, 0), - Point(1, 0), - Point(cos(pi/3), sin(pi/3)), - Point(cos(pi/2), sin(pi/2)), - Point(1,0), - Point(cos(-pi/3), sin(-pi/3)), - Point(cos(-pi/6), sin(-pi/6)), - Point(cos(5*pi/6), sin(-2*pi/6)), - }; - double expected [] = - { - 0, - 0, - cos(pi/3), - 0.8660254037844386, - 0, - 0.5, - 0.8660254037844386, - -0.31698729810778087 - }; - const int NPOINTS = sizeof(Points) / sizeof(*Points); - fprintf (f, " %d test cases\n\n", NPOINTS); - int ntests=0, res=0; - double dot=0, edot=0; - - for(int i=0; i<NPOINTS-1;i++) - { - dot = Points[i].ScalarP(Points[i+1]); - edot = expected[i]; - res += ( fabs(dot-edot)<0.001 )?1:0; - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), R(%.2f, %.2f), dot=%f edot=%f\n", ntests, res, Points[i]._x, Points[i]._y, Points[i+1]._x, Points[i+1]._y, dot, edot); - dot = Points[i+1].ScalarP(Points[i]); - res += ( fabs(dot-edot)<eps )?1:0; - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), R(%.2f, %.2f), dot=%f edot=%f\n\n", ntests, res, Points[i+1]._x, Points[i+1]._y, Points[i]._x, Points[i]._y, dot, edot); - } - fprintf (f, "\t+++++ Leave testScalarP() +++++\n\n"); - return (res == ntests)?1:0; + fprintf (f, "\t+++++ Enter testScalarP() +++++\n"); + Point Points[] = { + Point(1, 2), + Point(0, 0), + Point(1, 0), + Point(cos(pi/3), sin(pi/3)), + Point(cos(pi/2), sin(pi/2)), + Point(1,0), + Point(cos(-pi/3), sin(-pi/3)), + Point(cos(-pi/6), sin(-pi/6)), + Point(cos(5*pi/6), sin(-2*pi/6)), + }; + double expected [] = { + 0, + 0, + cos(pi/3), + 0.8660254037844386, + 0, + 0.5, + 0.8660254037844386, + -0.31698729810778087 + }; + const int NPOINTS = sizeof(Points) / sizeof(*Points); + fprintf (f, " %d test cases\n\n", NPOINTS); + int ntests=0, res=0; + double dot=0, edot=0; + + for(int i=0; i<NPOINTS-1; i++) { + dot = Points[i].ScalarP(Points[i+1]); + edot = expected[i]; + res += ( fabs(dot-edot)<0.001 )?1:0; + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), R(%.2f, %.2f), dot=%f edot=%f\n", ntests, res, Points[i]._x, Points[i]._y, Points[i+1]._x, Points[i+1]._y, dot, edot); + dot = Points[i+1].ScalarP(Points[i]); + res += ( fabs(dot-edot)<eps )?1:0; + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), R(%.2f, %.2f), dot=%f edot=%f\n\n", ntests, res, Points[i+1]._x, Points[i+1]._y, Points[i]._x, Points[i]._y, dot, edot); + } + fprintf (f, "\t+++++ Leave testScalarP() +++++\n\n"); + return (res == ntests)?1:0; } int testDet(FILE * f) { - fprintf (f, "\t+++++ Enter testDet() +++++\n"); - int ntests=0, res=0; - double det=0, edet=0; - Point Points[] = - { - Point(1, 2), - Point(0, 0), - Point(1, 0), - Point(cos(pi/3), sin(pi/3)), - Point(cos(pi/2), sin(pi/2)), - Point(1,0), - Point(cos(-pi/3), sin(-pi/3)), - Point(cos(-pi/6), sin(-pi/6)), - Point(cos(5*pi/6), sin(-2*pi/6)), - }; - double expected [] = - { - 0, - 0, - 0.866025403784, - 0.5, - -1.0, - -0.866025403784, - 0.5, - -1.18301270189 - }; - const int NPOINTS = sizeof(Points) / sizeof(*Points); - fprintf (f, " %d test cases\n\n", NPOINTS); - for(int i=0; i<NPOINTS-1;i++) - { - det = Points[i].Det(Points[i+1]); - edet = expected[i]; - res += ( fabs(det-edet)<0.001 )?1:0; - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), R(%.2f, %.2f), det=%f edet=%f\n", ntests, res, Points[i]._x, Points[i]._y, Points[i+1]._x, Points[i+1]._y, det, edet); - det = Points[i+1].Det(Points[i]); - res += ( fabs(det+edet)<eps )?1:0; //edet == -edet - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), R(%.2f, %.2f), det=%f edet=%f\n\n", ntests, res, Points[i+1]._x, Points[i+1]._y, Points[i]._x, Points[i]._y, det, edet); - } - - fprintf (f, "\t+++++ Leave testDet() +++++\n\n"); - return (res==ntests)?1:0; + fprintf (f, "\t+++++ Enter testDet() +++++\n"); + int ntests=0, res=0; + double det=0, edet=0; + Point Points[] = { + Point(1, 2), + Point(0, 0), + Point(1, 0), + Point(cos(pi/3), sin(pi/3)), + Point(cos(pi/2), sin(pi/2)), + Point(1,0), + Point(cos(-pi/3), sin(-pi/3)), + Point(cos(-pi/6), sin(-pi/6)), + Point(cos(5*pi/6), sin(-2*pi/6)), + }; + double expected [] = { + 0, + 0, + 0.866025403784, + 0.5, + -1.0, + -0.866025403784, + 0.5, + -1.18301270189 + }; + const int NPOINTS = sizeof(Points) / sizeof(*Points); + fprintf (f, " %d test cases\n\n", NPOINTS); + for(int i=0; i<NPOINTS-1; i++) { + det = Points[i].Det(Points[i+1]); + edet = expected[i]; + res += ( fabs(det-edet)<0.001 )?1:0; + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), R(%.2f, %.2f), det=%f edet=%f\n", ntests, res, Points[i]._x, Points[i]._y, Points[i+1]._x, Points[i+1]._y, det, edet); + det = Points[i+1].Det(Points[i]); + res += ( fabs(det+edet)<eps )?1:0; //edet == -edet + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), R(%.2f, %.2f), det=%f edet=%f\n\n", ntests, res, Points[i+1]._x, Points[i+1]._y, Points[i]._x, Points[i]._y, det, edet); + } + + fprintf (f, "\t+++++ Leave testDet() +++++\n\n"); + return (res==ntests)?1:0; } int testCoordTransToEllipse(FILE * f) { - fprintf (f, "\t+++++ Enter testCoordTransToEllipse() +++++\n"); - int ntests=0, res=0; - Point Points[] = - { - Point(1, 2), - Point(0, 0), - Point(1, 0), - Point(cos(pi/3), sin(pi/3)), - Point(cos(pi/2), sin(pi/2)), - Point(1,0), - Point(cos(-pi/3), sin(-pi/3)), - Point(cos(-pi/6), sin(-pi/6)), - Point(cos(5*pi/6), sin(-2*pi/6)), - }; - const int NPOINTS = sizeof(Points) / sizeof(*Points); - double cosphi=1, sinphi=0; - Point transPoint(0,0), expectedPoint(0,0); - Point Center(0,0); - fprintf (f, "\t\tcosphi=%.2f, sinphi=%.2f, Center(%.2f, %.2f)\n", cosphi, sinphi, Center._x, Center._y); - for(int i=0; i<NPOINTS-1;i++) - { - transPoint = Points[i].CoordTransToEllipse(Center, cosphi, sinphi); - res += ( transPoint == Points[i] )?1:0; //phi==0! - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), T(%.2f, %.2f)\n", ntests, res, Points[i]._x, Points[i]._y, transPoint._x, transPoint._y); - } + fprintf (f, "\t+++++ Enter testCoordTransToEllipse() +++++\n"); + int ntests=0, res=0; + Point Points[] = { + Point(1, 2), + Point(0, 0), + Point(1, 0), + Point(cos(pi/3), sin(pi/3)), + Point(cos(pi/2), sin(pi/2)), + Point(1,0), + Point(cos(-pi/3), sin(-pi/3)), + Point(cos(-pi/6), sin(-pi/6)), + Point(cos(5*pi/6), sin(-2*pi/6)), + }; + const int NPOINTS = sizeof(Points) / sizeof(*Points); + double cosphi=1, sinphi=0; + Point transPoint(0,0), expectedPoint(0,0); + Point Center(0,0); + fprintf (f, "\t\tcosphi=%.2f, sinphi=%.2f, Center(%.2f, %.2f)\n", cosphi, sinphi, Center._x, Center._y); + for(int i=0; i<NPOINTS-1; i++) { + transPoint = Points[i].CoordTransToEllipse(Center, cosphi, sinphi); + res += ( transPoint == Points[i] )?1:0; //phi==0! + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), T(%.2f, %.2f)\n", ntests, res, Points[i]._x, Points[i]._y, transPoint._x, transPoint._y); + } //-------------------------------------------------------------------------------------- - cosphi = 0.5; // pi/3 - sinphi = 0.8660254037844386; //pi/3 - fprintf (f, "\t\tcosphi=%.2f, sinphi=%.2f, Center(%.2f, %.2f)\n", cosphi, sinphi, Center._x, Center._y); - for(int i=0; i<NPOINTS-1;i++) - { - transPoint = Points[i].CoordTransToEllipse(Center, cosphi, sinphi); - expectedPoint = Points[i].Rotate(cosphi, -sinphi); - res += ( transPoint == expectedPoint )?1:0; //phi==0! - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), T(%.2f, %.2f), E(%.2f, %.2f)\n", ntests, res, Points[i]._x, Points[i]._y, transPoint._x, transPoint._y, expectedPoint._x, expectedPoint._y); - } + cosphi = 0.5; // pi/3 + sinphi = 0.8660254037844386; //pi/3 + fprintf (f, "\t\tcosphi=%.2f, sinphi=%.2f, Center(%.2f, %.2f)\n", cosphi, sinphi, Center._x, Center._y); + for(int i=0; i<NPOINTS-1; i++) { + transPoint = Points[i].CoordTransToEllipse(Center, cosphi, sinphi); + expectedPoint = Points[i].Rotate(cosphi, -sinphi); + res += ( transPoint == expectedPoint )?1:0; //phi==0! + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), T(%.2f, %.2f), E(%.2f, %.2f)\n", ntests, res, Points[i]._x, Points[i]._y, transPoint._x, transPoint._y, expectedPoint._x, expectedPoint._y); + } //-------------------------------------------------------------------------------------- - cosphi = 0.5; // -pi/3 - sinphi = -0.8660254037844386; // -pi/3 - fprintf (f, "\t\tcosphi=%.2f, sinphi=%.2f, Center(%.2f, %.2f)\n", cosphi, sinphi, Center._x, Center._y); - for(int i=0; i<NPOINTS-1;i++) - { - transPoint = Points[i].CoordTransToEllipse(Center, cosphi, sinphi); - expectedPoint = Points[i].Rotate(cosphi, -sinphi); - res += ( transPoint == expectedPoint )?1:0; //phi==0! - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), T(%.2f, %.2f), E(%.2f, %.2f)\n", ntests, res, Points[i]._x, Points[i]._y, transPoint._x, transPoint._y, expectedPoint._x, expectedPoint._y); - } + cosphi = 0.5; // -pi/3 + sinphi = -0.8660254037844386; // -pi/3 + fprintf (f, "\t\tcosphi=%.2f, sinphi=%.2f, Center(%.2f, %.2f)\n", cosphi, sinphi, Center._x, Center._y); + for(int i=0; i<NPOINTS-1; i++) { + transPoint = Points[i].CoordTransToEllipse(Center, cosphi, sinphi); + expectedPoint = Points[i].Rotate(cosphi, -sinphi); + res += ( transPoint == expectedPoint )?1:0; //phi==0! + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), T(%.2f, %.2f), E(%.2f, %.2f)\n", ntests, res, Points[i]._x, Points[i]._y, transPoint._x, transPoint._y, expectedPoint._x, expectedPoint._y); + } //-------------------------------------------------------------------------------------- - Center.SetX(1); - Center.SetY(1); - cosphi = 0.5; // pi/3 - sinphi = 0.8660254037844386; //pi/3 - fprintf (f, "\t\tcosphi=%.2f, sinphi=%.2f, Center(%.2f, %.2f)\n", cosphi, sinphi, Center._x, Center._y); - for(int i=0; i<NPOINTS-1;i++) - { - transPoint = Points[i].CoordTransToEllipse(Center, cosphi, sinphi); - expectedPoint = (Points[i]-Center).Rotate(cosphi, -sinphi); - res += ( transPoint == expectedPoint )?1:0; //phi==0! - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), T(%.2f, %.2f), E(%.2f, %.2f)\n", ntests, res, Points[i]._x, Points[i]._y, transPoint._x, transPoint._y, expectedPoint._x, expectedPoint._y); - } - fprintf (f, "\t+++++ Leave testCoordTransToEllipse() +++++\n\n"); - return (res==ntests)?1:0; + Center.SetX(1); + Center.SetY(1); + cosphi = 0.5; // pi/3 + sinphi = 0.8660254037844386; //pi/3 + fprintf (f, "\t\tcosphi=%.2f, sinphi=%.2f, Center(%.2f, %.2f)\n", cosphi, sinphi, Center._x, Center._y); + for(int i=0; i<NPOINTS-1; i++) { + transPoint = Points[i].CoordTransToEllipse(Center, cosphi, sinphi); + expectedPoint = (Points[i]-Center).Rotate(cosphi, -sinphi); + res += ( transPoint == expectedPoint )?1:0; //phi==0! + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), T(%.2f, %.2f), E(%.2f, %.2f)\n", ntests, res, Points[i]._x, Points[i]._y, transPoint._x, transPoint._y, expectedPoint._x, expectedPoint._y); + } + fprintf (f, "\t+++++ Leave testCoordTransToEllipse() +++++\n\n"); + return (res==ntests)?1:0; } int testCoordTransToCart(FILE * f) { - fprintf (f, "\t+++++ Enter testCoordTransToCart() +++++\n"); - int ntests=0, res=0; - Point Points[] = - { - Point(1, 2), - Point(0, 0), - Point(1, 0), - Point(cos(pi/3), sin(pi/3)), - Point(cos(pi/2), sin(pi/2)), - Point(1,0), - Point(cos(-pi/3), sin(-pi/3)), - Point(cos(-pi/6), sin(-pi/6)), - Point(cos(5*pi/6), sin(-2*pi/6)), - }; - - const int NPOINTS = sizeof(Points) / sizeof(*Points); - double cosphi=1, sinphi=0; - Point transPoint(0,0), expectedPoint(0,0); - Point Center(0,0); - fprintf (f, "\t\tcosphi=%.2f, sinphi=%.2f, Center(%.2f, %.2f)\n", cosphi, sinphi, Center._x, Center._y); - for(int i=0; i<NPOINTS-1;i++) - { - transPoint = Points[i].CoordTransToCart(Center, cosphi, sinphi); - res += ( transPoint == Points[i] )?1:0; //phi==0! - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), T(%.2f, %.2f)\n", ntests, res, Points[i]._x, Points[i]._y, transPoint._x, transPoint._y); - } + fprintf (f, "\t+++++ Enter testCoordTransToCart() +++++\n"); + int ntests=0, res=0; + Point Points[] = { + Point(1, 2), + Point(0, 0), + Point(1, 0), + Point(cos(pi/3), sin(pi/3)), + Point(cos(pi/2), sin(pi/2)), + Point(1,0), + Point(cos(-pi/3), sin(-pi/3)), + Point(cos(-pi/6), sin(-pi/6)), + Point(cos(5*pi/6), sin(-2*pi/6)), + }; + + const int NPOINTS = sizeof(Points) / sizeof(*Points); + double cosphi=1, sinphi=0; + Point transPoint(0,0), expectedPoint(0,0); + Point Center(0,0); + fprintf (f, "\t\tcosphi=%.2f, sinphi=%.2f, Center(%.2f, %.2f)\n", cosphi, sinphi, Center._x, Center._y); + for(int i=0; i<NPOINTS-1; i++) { + transPoint = Points[i].CoordTransToCart(Center, cosphi, sinphi); + res += ( transPoint == Points[i] )?1:0; //phi==0! + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), T(%.2f, %.2f)\n", ntests, res, Points[i]._x, Points[i]._y, transPoint._x, transPoint._y); + } //-------------------------------------------------------------------------------------- - cosphi = 0.5; // pi/3 - sinphi = 0.8660254037844386; //pi/3 - fprintf (f, "\t\tcosphi=%.2f, sinphi=%.2f, Center(%.2f, %.2f)\n", cosphi, sinphi, Center._x, Center._y); - for(int i=0; i<NPOINTS-1;i++) - { - transPoint = Points[i].CoordTransToCart(Center, cosphi, sinphi); - expectedPoint = Points[i].Rotate(cosphi, sinphi); - res += ( transPoint == expectedPoint )?1:0; //phi==0! - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), T(%.2f, %.2f), E(%.2f, %.2f)\n", ntests, res, Points[i]._x, Points[i]._y, transPoint._x, transPoint._y, expectedPoint._x, expectedPoint._y); - } + cosphi = 0.5; // pi/3 + sinphi = 0.8660254037844386; //pi/3 + fprintf (f, "\t\tcosphi=%.2f, sinphi=%.2f, Center(%.2f, %.2f)\n", cosphi, sinphi, Center._x, Center._y); + for(int i=0; i<NPOINTS-1; i++) { + transPoint = Points[i].CoordTransToCart(Center, cosphi, sinphi); + expectedPoint = Points[i].Rotate(cosphi, sinphi); + res += ( transPoint == expectedPoint )?1:0; //phi==0! + ntests++; + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), T(%.2f, %.2f), E(%.2f, %.2f)\n", ntests, res, Points[i]._x, Points[i]._y, transPoint._x, transPoint._y, expectedPoint._x, expectedPoint._y); + } //-------------------------------------------------------------------------------------- - cosphi = 0.5; // -pi/3 - sinphi = -0.8660254037844386; // -pi/3 - fprintf (f, "\t\tcosphi=%.2f, sinphi=%.2f, Center(%.2f, %.2f)\n", cosphi, sinphi, Center._x, Center._y); - + cosphi = 0.5; // -pi/3 + sinphi = -0.8660254037844386; // -pi/3 + fprintf (f, "\t\tcosphi=%.2f, sinphi=%.2f, Center(%.2f, %.2f)\n", cosphi, sinphi, Center._x, Center._y); - for(int i=0; i<NPOINTS-1;i++) - { - transPoint = Points[i].CoordTransToCart(Center, cosphi, sinphi); - expectedPoint = Points[i].Rotate(cosphi, sinphi); - res += ( transPoint == expectedPoint )?1:0; //phi==0! - ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), T(%.2f, %.2f), E(%.2f, %.2f)\n", ntests, res, Points[i]._x, Points[i]._y, transPoint._x, transPoint._y, expectedPoint._x, expectedPoint._y); + for(int i=0; i<NPOINTS-1; i++) { + transPoint = Points[i].CoordTransToCart(Center, cosphi, sinphi); + expectedPoint = Points[i].Rotate(cosphi, sinphi); + res += ( transPoint == expectedPoint )?1:0; //phi==0! + ntests++; - } + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), T(%.2f, %.2f), E(%.2f, %.2f)\n", ntests, res, Points[i]._x, Points[i]._y, transPoint._x, transPoint._y, expectedPoint._x, expectedPoint._y); + + } //-------------------------------------------------------------------------------------- - Center.SetX(1); - Center.SetY(1); - cosphi = 0.5; // pi/3 + Center.SetX(1); + Center.SetY(1); + cosphi = 0.5; // pi/3 - sinphi = 0.8660254037844386; //pi/3 + sinphi = 0.8660254037844386; //pi/3 - fprintf (f, "\t\tcosphi=%.2f, sinphi=%.2f, Center(%.2f, %.2f)\n", cosphi, sinphi, Center._x, Center._y); - for(int i=0; i<NPOINTS-1;i++) - { - transPoint = Points[i].CoordTransToCart(Center, cosphi, sinphi); + fprintf (f, "\t\tcosphi=%.2f, sinphi=%.2f, Center(%.2f, %.2f)\n", cosphi, sinphi, Center._x, Center._y); + for(int i=0; i<NPOINTS-1; i++) { + transPoint = Points[i].CoordTransToCart(Center, cosphi, sinphi); - expectedPoint = Points[i].Rotate(cosphi, sinphi)+Center; - res += ( transPoint == expectedPoint )?1:0; //phi==0! - ntests++; + expectedPoint = Points[i].Rotate(cosphi, sinphi)+Center; + res += ( transPoint == expectedPoint )?1:0; //phi==0! + ntests++; - fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), T(%.2f, %.2f), E(%.2f, %.2f)\n", ntests, res, Points[i]._x, Points[i]._y, transPoint._x, transPoint._y, expectedPoint._x, expectedPoint._y); - } + fprintf (f, "%2d. res=%2d, P(%.2f, %.2f), T(%.2f, %.2f), E(%.2f, %.2f)\n", ntests, res, Points[i]._x, Points[i]._y, transPoint._x, transPoint._y, expectedPoint._x, expectedPoint._y); + } - fprintf (f, "\t+++++ Leave testCoordTransToCart() +++++\n\n"); - return (res==ntests)?1:0; + fprintf (f, "\t+++++ Leave testCoordTransToCart() +++++\n\n"); + return (res==ntests)?1:0; } int testRotate(FILE * f) { - fprintf (f, "\t+++++ Enter testRotate() +++++\n"); - int ntests=0, res=0; -Point Points[] = - { - Point(1, 2), - Point(0, 0), - - Point(1, 0), - Point(cos(pi/3), sin(pi/3)), - Point(cos(pi/2), sin(pi/2)), - Point(1,0), - Point(cos(-pi/3), sin(-pi/3)), - Point(cos(-pi/6), sin(-pi/6)), - Point(cos(5*pi/6), sin(-2*pi/6)), - }; - double expected [] = - { - 0, - 0, - cos(pi/3), - 0.8660254037844386, - 0, - 0.5, - 0.8660254037844386, - -0.31698729810778087 - }; - const int NPOINTS = sizeof(Points) / sizeof(*Points); - fprintf (f, " %d test cases\n\n", NPOINTS); - - fprintf (f, "\t+++++ Leave testRotate() +++++\n\n"); - return (res==ntests)?1:0; + fprintf (f, "\t+++++ Enter testRotate() +++++\n"); + int ntests=0, res=0; + Point Points[] = { + Point(1, 2), + Point(0, 0), + + Point(1, 0), + Point(cos(pi/3), sin(pi/3)), + Point(cos(pi/2), sin(pi/2)), + Point(1,0), + Point(cos(-pi/3), sin(-pi/3)), + Point(cos(-pi/6), sin(-pi/6)), + Point(cos(5*pi/6), sin(-2*pi/6)), + }; + double expected [] = { + 0, + 0, + cos(pi/3), + 0.8660254037844386, + 0, + 0.5, + 0.8660254037844386, + -0.31698729810778087 + }; + const int NPOINTS = sizeof(Points) / sizeof(*Points); + fprintf (f, " %d test cases\n\n", NPOINTS); + + fprintf (f, "\t+++++ Leave testRotate() +++++\n\n"); + return (res==ntests)?1:0; } int main() { - FILE * f; - char fname[FILENAME_MAX] = "log_testClassPoint.txt"; - char cCurrentPath[FILENAME_MAX]; - f = fopen(fname, "w"); - if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) - { - return EXIT_FAILURE; - } - cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ - - fprintf (f, "The current working directory is %s\n\n", cCurrentPath); - - int res = 0, ntests = 0; - - res += testNorm(f); - ntests++; - res += testNormalized(f); - ntests++; - res += testScalarP(f); - ntests++; - res += testDet(f); - ntests++; - res += testCoordTransToEllipse(f); - ntests++; - res += testCoordTransToCart(f); - ntests++; - res += testRotate(f); - ntests++; - - fclose(f); - return (res==ntests)?EXIT_SUCCESS:EXIT_FAILURE; + FILE * f; + char fname[FILENAME_MAX] = "log_testClassPoint.txt"; + char cCurrentPath[FILENAME_MAX]; + f = fopen(fname, "w"); + if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) { + return EXIT_FAILURE; + } + cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ + + fprintf (f, "The current working directory is %s\n\n", cCurrentPath); + + int res = 0, ntests = 0; + + res += testNorm(f); + ntests++; + res += testNormalized(f); + ntests++; + res += testScalarP(f); + ntests++; + res += testDet(f); + ntests++; + res += testCoordTransToEllipse(f); + ntests++; + res += testCoordTransToCart(f); + ntests++; + res += testRotate(f); + ntests++; + + fclose(f); + return (res==ntests)?EXIT_SUCCESS:EXIT_FAILURE; } diff --git a/Utest/testEffectiveDistanceToEllipse.cpp b/Utest/testEffectiveDistanceToEllipse.cpp index 75548b1c14b0e0479ecc34ff9cf4477748c90be1..38147bcaad7e4549e6ec650a5819b9fdea8af072 100644 --- a/Utest/testEffectiveDistanceToEllipse.cpp +++ b/Utest/testEffectiveDistanceToEllipse.cpp @@ -2,219 +2,218 @@ #include <stdio.h> #include "../math/Mathematics.h" #include "../pedestrian/Ellipse.h" -#include <time.h> +#include <time.h> #ifdef WINDOWS #include <direct.h> - #define GetCurrentDir _getcwd +#define GetCurrentDir _getcwd #else #include <unistd.h> - #define GetCurrentDir getcwd - #endif +#define GetCurrentDir getcwd +#endif OutputHandler* Log; int testEffectiveDistanceToEllipse() { - clock_t t1, t2; - char cCurrentPath[FILENAME_MAX]; - if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) - { - return EXIT_FAILURE; - } - cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ - - FILE * f; - char fname[FILENAME_MAX] = "log_testEffectiveDistanceToEllipse.txt"; - f = fopen(fname, "w"); - fprintf (f, "The current working directory is %s\n\n", cCurrentPath); - double dist, effdist; - int res=0; - double a=2.0, // semi-axis - b=1.5; // orthogonal semi-axis - int ntests=0; - JEllipse E1, E2; - double x2, y2; //E2 center - t1 = clock(); - - E1.SetCenter( Point(0,0) ); - E1.SetV0(1); - E1.SetV( Point(0,0) ); - E1.SetAmin(a); - E1.SetBmax(b); + clock_t t1, t2; + char cCurrentPath[FILENAME_MAX]; + if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) { + return EXIT_FAILURE; + } + cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ + + FILE * f; + char fname[FILENAME_MAX] = "log_testEffectiveDistanceToEllipse.txt"; + f = fopen(fname, "w"); + fprintf (f, "The current working directory is %s\n\n", cCurrentPath); + double dist, effdist; + int res=0; + double a=2.0, // semi-axis + b=1.5; // orthogonal semi-axis + int ntests=0; + JEllipse E1, E2; + double x2, y2; //E2 center + t1 = clock(); + + E1.SetCenter( Point(0,0) ); + E1.SetV0(1); + E1.SetV( Point(0,0) ); + E1.SetAmin(a); + E1.SetBmax(b); // case 1 - x2 = 10; - y2 = 0; - E2.SetCenter( Point(x2, y2) ); - E2.SetV0(1); - E2.SetV( Point(0,0) ); - E2.SetAmin(a); - E2.SetBmax(b); - - effdist = E1.EffectiveDistanceToEllipse(E2, &dist); - res += ((effdist==(fabs(x2)-2*a)) && (dist == fabs(x2)) )?1:0; - fprintf (f, "%d. dist=%.2f (expected 10)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1, dist, effdist, x2-2*a,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); - ntests++; -// case 2 - x2 = -10; - y2 = 0; - E2.SetCenter( Point(x2, y2) ); - E2.SetV0(1); - E2.SetV( Point(0,0) ); - E2.SetAmin(a); - E2.SetBmax(b); - effdist = E1.EffectiveDistanceToEllipse(E2, &dist); - res += ((effdist==(fabs(x2)-2*a)) && (dist == fabs(x2)) )?1:0; - fprintf (f, "%d. dist=%.2f (expected 10)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, effdist, fabs(x2)-2*a,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); - ntests++; - -// case 3 contact - x2 = 2*a; - y2 = 0; - E2.SetCenter( Point(x2, y2) ); - E2.SetV0(1); - E2.SetV( Point(0,0) ); - E2.SetAmin(a); - E2.SetBmax(b); - effdist = E1.EffectiveDistanceToEllipse(E2, &dist); - res += ((effdist==(fabs(x2)-2*a)) && (dist == fabs(x2)) )?1:0; - fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(x2), effdist, fabs(x2)-2*a,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); - ntests++; - -// case 4 overlap - x2 = 2*a-1.; - y2 = 0; - E2.SetCenter( Point(x2, y2) ); - E2.SetV0(1); - E2.SetV( Point(0,0) ); - E2.SetAmin(a); - E2.SetBmax(b); - effdist = E1.EffectiveDistanceToEllipse(E2, &dist); - res += ((effdist==(fabs(x2)-2*a)) && (dist == fabs(x2)) )?1:0; - fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(x2), effdist, fabs(x2)-2*a,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); - ntests++; + x2 = 10; + y2 = 0; + E2.SetCenter( Point(x2, y2) ); + E2.SetV0(1); + E2.SetV( Point(0,0) ); + E2.SetAmin(a); + E2.SetBmax(b); + + effdist = E1.EffectiveDistanceToEllipse(E2, &dist); + res += ((effdist==(fabs(x2)-2*a)) && (dist == fabs(x2)) )?1:0; + fprintf (f, "%d. dist=%.2f (expected 10)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1, dist, effdist, x2-2*a,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); + ntests++; +// case 2 + x2 = -10; + y2 = 0; + E2.SetCenter( Point(x2, y2) ); + E2.SetV0(1); + E2.SetV( Point(0,0) ); + E2.SetAmin(a); + E2.SetBmax(b); + effdist = E1.EffectiveDistanceToEllipse(E2, &dist); + res += ((effdist==(fabs(x2)-2*a)) && (dist == fabs(x2)) )?1:0; + fprintf (f, "%d. dist=%.2f (expected 10)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, effdist, fabs(x2)-2*a,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); + ntests++; + +// case 3 contact + x2 = 2*a; + y2 = 0; + E2.SetCenter( Point(x2, y2) ); + E2.SetV0(1); + E2.SetV( Point(0,0) ); + E2.SetAmin(a); + E2.SetBmax(b); + effdist = E1.EffectiveDistanceToEllipse(E2, &dist); + res += ((effdist==(fabs(x2)-2*a)) && (dist == fabs(x2)) )?1:0; + fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(x2), effdist, fabs(x2)-2*a,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); + ntests++; + +// case 4 overlap + x2 = 2*a-1.; + y2 = 0; + E2.SetCenter( Point(x2, y2) ); + E2.SetV0(1); + E2.SetV( Point(0,0) ); + E2.SetAmin(a); + E2.SetBmax(b); + effdist = E1.EffectiveDistanceToEllipse(E2, &dist); + res += ((effdist==(fabs(x2)-2*a)) && (dist == fabs(x2)) )?1:0; + fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(x2), effdist, fabs(x2)-2*a,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); + ntests++; // case 6 y-axis - x2 = 0.; - y2 = 5; - E2.SetCenter( Point(x2, y2) ); - E2.SetV0(1); - E2.SetV( Point(0,0) ); - E2.SetAmin(a); - E2.SetBmax(b); - effdist = E1.EffectiveDistanceToEllipse(E2, &dist); - res += ((effdist==(fabs(y2)-2*b)) && (dist == fabs(y2)) )?1:0; - fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(y2), effdist, fabs(y2)-2*b,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); - ntests++ ; + x2 = 0.; + y2 = 5; + E2.SetCenter( Point(x2, y2) ); + E2.SetV0(1); + E2.SetV( Point(0,0) ); + E2.SetAmin(a); + E2.SetBmax(b); + effdist = E1.EffectiveDistanceToEllipse(E2, &dist); + res += ((effdist==(fabs(y2)-2*b)) && (dist == fabs(y2)) )?1:0; + fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(y2), effdist, fabs(y2)-2*b,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); + ntests++ ; // case 7 y-axis - x2 = 0.; - y2 = -5; - E2.SetCenter( Point(x2, y2) ); - E2.SetV0(1); - E2.SetV( Point(0,0) ); - E2.SetAmin(a); - E2.SetBmax(b); - effdist = E1.EffectiveDistanceToEllipse(E2, &dist); - res += ((effdist==(fabs(y2)-2*b)) && (dist == fabs(y2)) )?1:0; - fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(y2), effdist, fabs(y2)-2*b,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); - ntests++ ; + x2 = 0.; + y2 = -5; + E2.SetCenter( Point(x2, y2) ); + E2.SetV0(1); + E2.SetV( Point(0,0) ); + E2.SetAmin(a); + E2.SetBmax(b); + effdist = E1.EffectiveDistanceToEllipse(E2, &dist); + res += ((effdist==(fabs(y2)-2*b)) && (dist == fabs(y2)) )?1:0; + fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(y2), effdist, fabs(y2)-2*b,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); + ntests++ ; // case 8 y-axis - x2 = 0.; - y2 = 2*b; - E2.SetCenter( Point(x2, y2) ); - E2.SetV0(1); - E2.SetV( Point(0,0) ); - E2.SetAmin(a); - E2.SetBmax(b); - effdist = E1.EffectiveDistanceToEllipse(E2, &dist); - res += ((effdist==(fabs(y2)-2*b)) && (dist == fabs(y2)) )?1:0; - fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(y2), effdist, fabs(y2)-2*b,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); - ntests++ ; + x2 = 0.; + y2 = 2*b; + E2.SetCenter( Point(x2, y2) ); + E2.SetV0(1); + E2.SetV( Point(0,0) ); + E2.SetAmin(a); + E2.SetBmax(b); + effdist = E1.EffectiveDistanceToEllipse(E2, &dist); + res += ((effdist==(fabs(y2)-2*b)) && (dist == fabs(y2)) )?1:0; + fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(y2), effdist, fabs(y2)-2*b,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); + ntests++ ; // case 9 y-axis - x2 = 0.; - y2 = -2*b; - E2.SetCenter( Point(x2, y2) ); - E2.SetV0(1); - E2.SetV( Point(0,0) ); - E2.SetAmin(a); - E2.SetBmax(b); - effdist = E1.EffectiveDistanceToEllipse(E2, &dist); - res += ((effdist==(fabs(y2)-2*b)) && (dist == fabs(y2)) )?1:0; - fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(y2), effdist, fabs(y2)-2*b,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); - ntests++ ; + x2 = 0.; + y2 = -2*b; + E2.SetCenter( Point(x2, y2) ); + E2.SetV0(1); + E2.SetV( Point(0,0) ); + E2.SetAmin(a); + E2.SetBmax(b); + effdist = E1.EffectiveDistanceToEllipse(E2, &dist); + res += ((effdist==(fabs(y2)-2*b)) && (dist == fabs(y2)) )?1:0; + fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(y2), effdist, fabs(y2)-2*b,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); + ntests++ ; // case 10 y-axis overlap - x2 = 0.; - y2 = -2*b+b; - E2.SetCenter( Point(x2, y2) ); - E2.SetV0(1); - E2.SetV( Point(0,0) ); - E2.SetAmin(a); - E2.SetBmax(b); - effdist = E1.EffectiveDistanceToEllipse(E2, &dist); - res += ((effdist==(fabs(y2)-2*b)) && (dist == fabs(y2)) )?1:0; - fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(y2), effdist, fabs(y2)-2*b,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); - ntests++ ; + x2 = 0.; + y2 = -2*b+b; + E2.SetCenter( Point(x2, y2) ); + E2.SetV0(1); + E2.SetV( Point(0,0) ); + E2.SetAmin(a); + E2.SetBmax(b); + effdist = E1.EffectiveDistanceToEllipse(E2, &dist); + res += ((effdist==(fabs(y2)-2*b)) && (dist == fabs(y2)) )?1:0; + fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(y2), effdist, fabs(y2)-2*b,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); + ntests++ ; // case 11 y-axis overlap - x2 = 0.; - y2 = 2*b - b; - E2.SetCenter( Point(x2, y2) ); - E2.SetV0(1); - E2.SetV( Point(0,0) ); - E2.SetAmin(a); - E2.SetBmax(b); - effdist = E1.EffectiveDistanceToEllipse(E2, &dist); - res += ((effdist==(fabs(y2)-2*b)) && (dist == fabs(y2)) )?1:0; - fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(y2), effdist, fabs(y2)-2*b,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); - ntests++ ; - -// case 5 total overlap - x2 = 0.; - y2 = 0; - E2.SetCenter( Point(x2, y2) ); - E2.SetV0(1); - E2.SetV( Point(0,0) ); - E2.SetAmin(a); - E2.SetBmax(b); - effdist = E1.EffectiveDistanceToEllipse(E2, &dist); - res += ((effdist==(fabs(x2)-2*a)) && (dist == fabs(x2)) )?1:0; - fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(x2), effdist, fabs(x2)-2*a,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); - ntests++ ; - - -// case 12 ~total overlap - x2 = 0.001; - y2 = 0; - E2.SetCenter( Point(x2, y2) ); - E2.SetV0(1); - E2.SetV( Point(0,0) ); - E2.SetAmin(a); - E2.SetBmax(b); - effdist = E1.EffectiveDistanceToEllipse(E2, &dist); - res += ((effdist==(fabs(x2)-2*a)) && (dist == fabs(x2)) )?1:0; - fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%f, %f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(x2), effdist, fabs(x2)-2*a,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); - ntests++ ; - - - //calculate run time - //////////////////////////////////////////////////////////////// - // for (int i =0; i<1000; i++) - // for (int j =0; j<1000;j++) - // E1.EffectiveDistanceToEllipse(E2, &dist); - /////////////////////////////////////////////////////////////// - t2 = clock(); - double elapsed_secs = double(t2 - t1) / CLOCKS_PER_SEC; - fprintf (f, "Time: %d clicks (%f seconds).\n",(int)(t2-t1) , elapsed_secs); - - fclose(f); - return (res==ntests)?EXIT_SUCCESS:EXIT_FAILURE; + x2 = 0.; + y2 = 2*b - b; + E2.SetCenter( Point(x2, y2) ); + E2.SetV0(1); + E2.SetV( Point(0,0) ); + E2.SetAmin(a); + E2.SetBmax(b); + effdist = E1.EffectiveDistanceToEllipse(E2, &dist); + res += ((effdist==(fabs(y2)-2*b)) && (dist == fabs(y2)) )?1:0; + fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(y2), effdist, fabs(y2)-2*b,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); + ntests++ ; + +// case 5 total overlap + x2 = 0.; + y2 = 0; + E2.SetCenter( Point(x2, y2) ); + E2.SetV0(1); + E2.SetV( Point(0,0) ); + E2.SetAmin(a); + E2.SetBmax(b); + effdist = E1.EffectiveDistanceToEllipse(E2, &dist); + res += ((effdist==(fabs(x2)-2*a)) && (dist == fabs(x2)) )?1:0; + fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%.2f, %.2f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(x2), effdist, fabs(x2)-2*a,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); + ntests++ ; + + +// case 12 ~total overlap + x2 = 0.001; + y2 = 0; + E2.SetCenter( Point(x2, y2) ); + E2.SetV0(1); + E2.SetV( Point(0,0) ); + E2.SetAmin(a); + E2.SetBmax(b); + effdist = E1.EffectiveDistanceToEllipse(E2, &dist); + res += ((effdist==(fabs(x2)-2*a)) && (dist == fabs(x2)) )?1:0; + fprintf (f, "%d. dist=%.2f (expected %.2f)\t effdist=%.2f (expected %.2f) \t E1(%.2f, %.2f)\t E2(%f, %f)\t a=%.2f\t b=%.2f\t res=%d\n",ntests+1,dist, fabs(x2), effdist, fabs(x2)-2*a,E1.GetCenter().GetX(), E1.GetCenter().GetY(), E2.GetCenter().GetX(), E2.GetCenter().GetY(), a, b, res); + ntests++ ; + + + //calculate run time + //////////////////////////////////////////////////////////////// + // for (int i =0; i<1000; i++) + // for (int j =0; j<1000;j++) + // E1.EffectiveDistanceToEllipse(E2, &dist); + /////////////////////////////////////////////////////////////// + t2 = clock(); + double elapsed_secs = double(t2 - t1) / CLOCKS_PER_SEC; + fprintf (f, "Time: %d clicks (%f seconds).\n",(int)(t2-t1) , elapsed_secs); + + fclose(f); + return (res==ntests)?EXIT_SUCCESS:EXIT_FAILURE; } int main() { - return testEffectiveDistanceToEllipse(); + return testEffectiveDistanceToEllipse(); } diff --git a/Utest/testEffectiveDistanceToLine.cpp b/Utest/testEffectiveDistanceToLine.cpp index 8da752245fd651dc57c331d3b5541b8765e97235..c2304bc45118b1e3ba5b5730b6aee062b3fe484d 100644 --- a/Utest/testEffectiveDistanceToLine.cpp +++ b/Utest/testEffectiveDistanceToLine.cpp @@ -6,95 +6,94 @@ #ifdef WINDOWS #include <direct.h> - #define GetCurrentDir _getcwd +#define GetCurrentDir _getcwd #else #include <unistd.h> - #define GetCurrentDir getcwd - #endif +#define GetCurrentDir getcwd +#endif OutputHandler* Log; int testEffectiveDistanceToLine() { - char cCurrentPath[FILENAME_MAX]; - if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) - { - return EXIT_FAILURE; - } - cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ - - FILE * f; - char fname[FILENAME_MAX] = "log_testEffectiveDistanceToLine.txt"; - f = fopen(fname, "w"); - fprintf (f, "The current working directory is %s\n\n", cCurrentPath); - double dist; - int res=0; - double a=2.0, // semi-axis - b=1.5; // orthogonal semi-axis - int ntests=0; - JEllipse E; - E.SetCenter( Point(0,0) ); - E.SetV0(1); - E.SetV( Point(0,0) ); - E.SetAmin(a); - E.SetBmax(b); - // parallel y - Point P1(2*a, 0); - Point P2(2*a, 3); - Line L(P1, P2); - - dist = E.EffectiveDistanceToLine(L); - res += (dist==a)?1:0; - ntests++; - fprintf (f, "%2d. dist=%.2f\t Line (%.2f, %.2f)--(%.2f, %.2f) a=%.2f\t b=%.2f\t res=%d\n",ntests, dist, P1.GetX(), P1.GetY(), P2.GetX(), P2.GetY(), a, b, res); - - // parallel y - P1.SetX(-3*a); - P1.SetY(0); - P2.SetX(-3*a); - P2.SetY(3); - L.SetPoint1( P1 ); - L.SetPoint2( P2 ); - - dist = E.EffectiveDistanceToLine(L); - res += (dist==2*a)?1:0; - ntests++; - fprintf (f, "%2d. dist=%.2f\t Line (%.2f, %.2f)--(%.2f, %.2f) a=%.2f\t b=%.2f\t res=%d\n",ntests, dist, P1.GetX(), P1.GetY(), P2.GetX(), P2.GetY(), a, b, res); - -// parallel x - P1.SetX(0); - P1.SetY(2*b); - P2.SetX(3); - P2.SetY(2*b); - L.SetPoint1( P1 ); - L.SetPoint2( P2 ); - - - dist = E.EffectiveDistanceToLine(L); - res += (dist==b)?1:0; - ntests++; - fprintf (f, "%2d. dist=%.2f\t Line (%.2f, %.2f)--(%.2f, %.2f) a=%.2f\t b=%.2f\t res=%d\n",ntests, dist, P1.GetX(), P1.GetY(), P2.GetX(), P2.GetY(), a, b, res); - -// parallel x - P1.SetX(0); - P1.SetY(-2*b); - P2.SetX(3); - P2.SetY(-2*b); - L.SetPoint1( P1 ); - L.SetPoint2( P2 ); - - - dist = E.EffectiveDistanceToLine(L); - res += (dist==b)?1:0; - ntests++; - fprintf (f, "%2d. dist=%.2f\t Line (%.2f, %.2f)--(%.2f, %.2f) a=%.2f\t b=%.2f\t res=%d\n",ntests, dist, P1.GetX(), P1.GetY(), P2.GetX(), P2.GetY(), a, b, res); - - - fclose(f); - return (res==ntests)?EXIT_SUCCESS:EXIT_FAILURE; + char cCurrentPath[FILENAME_MAX]; + if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) { + return EXIT_FAILURE; + } + cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ + + FILE * f; + char fname[FILENAME_MAX] = "log_testEffectiveDistanceToLine.txt"; + f = fopen(fname, "w"); + fprintf (f, "The current working directory is %s\n\n", cCurrentPath); + double dist; + int res=0; + double a=2.0, // semi-axis + b=1.5; // orthogonal semi-axis + int ntests=0; + JEllipse E; + E.SetCenter( Point(0,0) ); + E.SetV0(1); + E.SetV( Point(0,0) ); + E.SetAmin(a); + E.SetBmax(b); + // parallel y + Point P1(2*a, 0); + Point P2(2*a, 3); + Line L(P1, P2); + + dist = E.EffectiveDistanceToLine(L); + res += (dist==a)?1:0; + ntests++; + fprintf (f, "%2d. dist=%.2f\t Line (%.2f, %.2f)--(%.2f, %.2f) a=%.2f\t b=%.2f\t res=%d\n",ntests, dist, P1.GetX(), P1.GetY(), P2.GetX(), P2.GetY(), a, b, res); + + // parallel y + P1.SetX(-3*a); + P1.SetY(0); + P2.SetX(-3*a); + P2.SetY(3); + L.SetPoint1( P1 ); + L.SetPoint2( P2 ); + + dist = E.EffectiveDistanceToLine(L); + res += (dist==2*a)?1:0; + ntests++; + fprintf (f, "%2d. dist=%.2f\t Line (%.2f, %.2f)--(%.2f, %.2f) a=%.2f\t b=%.2f\t res=%d\n",ntests, dist, P1.GetX(), P1.GetY(), P2.GetX(), P2.GetY(), a, b, res); + +// parallel x + P1.SetX(0); + P1.SetY(2*b); + P2.SetX(3); + P2.SetY(2*b); + L.SetPoint1( P1 ); + L.SetPoint2( P2 ); + + + dist = E.EffectiveDistanceToLine(L); + res += (dist==b)?1:0; + ntests++; + fprintf (f, "%2d. dist=%.2f\t Line (%.2f, %.2f)--(%.2f, %.2f) a=%.2f\t b=%.2f\t res=%d\n",ntests, dist, P1.GetX(), P1.GetY(), P2.GetX(), P2.GetY(), a, b, res); + +// parallel x + P1.SetX(0); + P1.SetY(-2*b); + P2.SetX(3); + P2.SetY(-2*b); + L.SetPoint1( P1 ); + L.SetPoint2( P2 ); + + + dist = E.EffectiveDistanceToLine(L); + res += (dist==b)?1:0; + ntests++; + fprintf (f, "%2d. dist=%.2f\t Line (%.2f, %.2f)--(%.2f, %.2f) a=%.2f\t b=%.2f\t res=%d\n",ntests, dist, P1.GetX(), P1.GetY(), P2.GetX(), P2.GetY(), a, b, res); + + + fclose(f); + return (res==ntests)?EXIT_SUCCESS:EXIT_FAILURE; } int main() { - return testEffectiveDistanceToLine(); + return testEffectiveDistanceToLine(); } diff --git a/Utest/testGetArea.cpp b/Utest/testGetArea.cpp index 185531593c0c88c33f79eadeff08943a67b1ca2a..012e6d302f6187edd98f104fb5772e466a4c967a 100644 --- a/Utest/testGetArea.cpp +++ b/Utest/testGetArea.cpp @@ -6,11 +6,11 @@ #ifdef WINDOWS #include <direct.h> - #define GetCurrentDir _getcwd +#define GetCurrentDir _getcwd #else #include <unistd.h> - #define GetCurrentDir getcwd - #endif +#define GetCurrentDir getcwd +#endif OutputHandler* Log; @@ -18,65 +18,64 @@ OutputHandler* Log; //int testPointOnEllipse(int argc, char* argv[]) int testGetArea() { - char cCurrentPath[FILENAME_MAX]; - if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) - { - return EXIT_FAILURE; - } - cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ + char cCurrentPath[FILENAME_MAX]; + if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) { + return EXIT_FAILURE; + } + cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ - FILE * f; - char fname[FILENAME_MAX] = "log_testGetArea.txt"; - // strcpy(fname, cCurrentPath); - // strcat(fname, "logs/log_testPointOnEllipse.txt"); - f = fopen(fname, "w"); - fprintf (f, "The current working directory is %s\n\n", cCurrentPath); - int ntests=0, res=0; - double pi = 3.141592653589793; - JEllipse E; - double a=2.0; - double b=4.0; - // #1 - E.SetCenter( Point(0,0) ); - E.SetV0(1); - E.SetV( Point(0,0) ); - E.SetAmin(a); - E.SetBmax(b); - res = ( fabs(E.GetArea() - a*b*pi) < 0.001 )?1:0; - fprintf (f, "a=%.2f\t b=%.2f\t area=%.2f\t expected=%.2f\t res=%d\t\n",a, b, E.GetArea(), a*b*pi, res); - ntests++; - // #2 - E.SetCenter( Point(10,-4) ); - res += ( fabs(E.GetArea() - a*b*pi) < 0.001 )?1:0; - fprintf (f, "a=%.2f\t b=%.2f\t area=%.2f\t expected=%.2f\t res=%d\t\n",a, b, E.GetArea(), a*b*pi, res); - ntests++; - // #3 - E.SetCenter( Point(10,-4) ); - E.SetAmin(b); - E.SetBmax(a); - res += ( fabs(E.GetArea() - a*b*pi) < 0.001 )?1:0; - fprintf (f, "a=%.2f\t b=%.2f\t area=%.2f\t expected=%.2f\t res=%d\t\n",a, b, E.GetArea(), a*b*pi, res); - ntests++; + FILE * f; + char fname[FILENAME_MAX] = "log_testGetArea.txt"; + // strcpy(fname, cCurrentPath); + // strcat(fname, "logs/log_testPointOnEllipse.txt"); + f = fopen(fname, "w"); + fprintf (f, "The current working directory is %s\n\n", cCurrentPath); + int ntests=0, res=0; + double pi = 3.141592653589793; + JEllipse E; + double a=2.0; + double b=4.0; + // #1 + E.SetCenter( Point(0,0) ); + E.SetV0(1); + E.SetV( Point(0,0) ); + E.SetAmin(a); + E.SetBmax(b); + res = ( fabs(E.GetArea() - a*b*pi) < 0.001 )?1:0; + fprintf (f, "a=%.2f\t b=%.2f\t area=%.2f\t expected=%.2f\t res=%d\t\n",a, b, E.GetArea(), a*b*pi, res); + ntests++; + // #2 + E.SetCenter( Point(10,-4) ); + res += ( fabs(E.GetArea() - a*b*pi) < 0.001 )?1:0; + fprintf (f, "a=%.2f\t b=%.2f\t area=%.2f\t expected=%.2f\t res=%d\t\n",a, b, E.GetArea(), a*b*pi, res); + ntests++; + // #3 + E.SetCenter( Point(10,-4) ); + E.SetAmin(b); + E.SetBmax(a); + res += ( fabs(E.GetArea() - a*b*pi) < 0.001 )?1:0; + fprintf (f, "a=%.2f\t b=%.2f\t area=%.2f\t expected=%.2f\t res=%d\t\n",a, b, E.GetArea(), a*b*pi, res); + ntests++; - // #4 - E.SetCenter( Point(-12.2, 5.1) ); - a *= 0.6; - b *= 1.3; - E.SetAmin(a); - E.SetBmax(b); - res += ( fabs(E.GetArea() - a*b*pi) < 0.001 )?1:0; - fprintf (f, "a=%.2f\t b=%.2f\t area=%.2f\t expected=%.2f\t res=%d\t\n",a, b, E.GetArea(), a*b*pi, res); - ntests++; + // #4 + E.SetCenter( Point(-12.2, 5.1) ); + a *= 0.6; + b *= 1.3; + E.SetAmin(a); + E.SetBmax(b); + res += ( fabs(E.GetArea() - a*b*pi) < 0.001 )?1:0; + fprintf (f, "a=%.2f\t b=%.2f\t area=%.2f\t expected=%.2f\t res=%d\t\n",a, b, E.GetArea(), a*b*pi, res); + ntests++; - - fclose(f); - return (res==ntests)?EXIT_SUCCESS:EXIT_FAILURE; + + fclose(f); + return (res==ntests)?EXIT_SUCCESS:EXIT_FAILURE; } int main(int argc, char * argv[]) { - // fprintf(stdout, "%s Version %d.%d\n", argv[0], JPSCORE_MINOR_VERSION, JPSCORE_MAJOR_VERSION); - return testGetArea(); + // fprintf(stdout, "%s Version %d.%d\n", argv[0], JPSCORE_MINOR_VERSION, JPSCORE_MAJOR_VERSION); + return testGetArea(); } diff --git a/Utest/testIsInside.cpp b/Utest/testIsInside.cpp index cf5b61e5d26de728d0ee70e156fb5d1369a205bb..7b364132ffca45c702f55032fdc0a6764165bb4b 100644 --- a/Utest/testIsInside.cpp +++ b/Utest/testIsInside.cpp @@ -6,11 +6,11 @@ #ifdef WINDOWS #include <direct.h> - #define GetCurrentDir _getcwd +#define GetCurrentDir _getcwd #else #include <unistd.h> - #define GetCurrentDir getcwd - #endif +#define GetCurrentDir getcwd +#endif OutputHandler* Log; @@ -19,124 +19,123 @@ OutputHandler* Log; int testIsInside() { - char cCurrentPath[FILENAME_MAX]; - if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) - { - return EXIT_FAILURE; - } - cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ - - FILE * f; - char fname[FILENAME_MAX] = "log_testIsInside.txt"; - // strcpy(fname, cCurrentPath); - // strcat(fname, "logs/log_testPointOnEllipse.txt"); - f = fopen(fname, "w"); - fprintf (f, "The current working directory is %s\n\n", cCurrentPath); - int ntests=0, res=0; - float a=2.0, b=5.0; - JEllipse E; - Point P; - //double px, py; - E.SetCenter( Point(0,0) ); - E.SetV0(1); - E.SetV( Point(0,0) ); - E.SetAmin(a); - E.SetBmax(b); - // P == E.center - P.SetX(0); - P.SetY(0); - res += ( E.IsInside(P) == true)?1:0; - ntests++; - fprintf (f, "%3d. E(%-4.2f, %-4.2f), a=%-4.2f, b=%-4.2f, P(%4.2f, %4.2f) res=%-3d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - // P ~ E.center - - P.SetX(0.); - P.SetY(-0.3); - res += ( E.IsInside(P) == true)?1:0; - ntests++; - fprintf (f, "%3d. E(%-4.2f, %-4.2f), a=%-4.2f, b=%-4.2f, P(%4.2f, %4.2f) res=%-3d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - // P ~ E.center - P.SetX(-0.73); - P.SetY(-0.3); - res += ( E.IsInside(P) == true)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - // P semi-axis - P.SetX(a); - P.SetY(0); - res += ( E.IsInside(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - // P semi-axis - P.SetX(-a); - P.SetY(0); - res += ( E.IsInside(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - // P ~ semi-axis - P.SetX(0); - P.SetY(b); - res += ( E.IsInside(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - // P ~ semi-axis - P.SetX(0); - P.SetY(-b); - res += ( E.IsInside(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - // P outside - P.SetX(a); - P.SetY(-b); - res += ( E.IsInside(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - // P outside - P.SetX(2*a); - P.SetY(3.1*b); - res += ( E.IsInside(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - - // P outside - P.SetX(3*a); - P.SetY(-3.5*b); - res += ( E.IsInside(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - - // P outside - P.SetX(-5*a); - P.SetY(-2*b); - res += ( E.IsInside(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - - // P outside - P.SetX(-1.1*a); - P.SetY(-1.1*b); - res += ( E.IsInside(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + char cCurrentPath[FILENAME_MAX]; + if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) { + return EXIT_FAILURE; + } + cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ + + FILE * f; + char fname[FILENAME_MAX] = "log_testIsInside.txt"; + // strcpy(fname, cCurrentPath); + // strcat(fname, "logs/log_testPointOnEllipse.txt"); + f = fopen(fname, "w"); + fprintf (f, "The current working directory is %s\n\n", cCurrentPath); + int ntests=0, res=0; + float a=2.0, b=5.0; + JEllipse E; + Point P; + //double px, py; + E.SetCenter( Point(0,0) ); + E.SetV0(1); + E.SetV( Point(0,0) ); + E.SetAmin(a); + E.SetBmax(b); + // P == E.center + P.SetX(0); + P.SetY(0); + res += ( E.IsInside(P) == true)?1:0; + ntests++; + fprintf (f, "%3d. E(%-4.2f, %-4.2f), a=%-4.2f, b=%-4.2f, P(%4.2f, %4.2f) res=%-3d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + // P ~ E.center + + P.SetX(0.); + P.SetY(-0.3); + res += ( E.IsInside(P) == true)?1:0; + ntests++; + fprintf (f, "%3d. E(%-4.2f, %-4.2f), a=%-4.2f, b=%-4.2f, P(%4.2f, %4.2f) res=%-3d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + // P ~ E.center + P.SetX(-0.73); + P.SetY(-0.3); + res += ( E.IsInside(P) == true)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + // P semi-axis + P.SetX(a); + P.SetY(0); + res += ( E.IsInside(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + // P semi-axis + P.SetX(-a); + P.SetY(0); + res += ( E.IsInside(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + // P ~ semi-axis + P.SetX(0); + P.SetY(b); + res += ( E.IsInside(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + // P ~ semi-axis + P.SetX(0); + P.SetY(-b); + res += ( E.IsInside(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + // P outside + P.SetX(a); + P.SetY(-b); + res += ( E.IsInside(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + +// P outside + P.SetX(2*a); + P.SetY(3.1*b); + res += ( E.IsInside(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + +// P outside + P.SetX(3*a); + P.SetY(-3.5*b); + res += ( E.IsInside(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + +// P outside + P.SetX(-5*a); + P.SetY(-2*b); + res += ( E.IsInside(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + +// P outside + P.SetX(-1.1*a); + P.SetY(-1.1*b); + res += ( E.IsInside(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); //----------------------------------------------------------------- - - fclose(f); - return (res==ntests)?EXIT_SUCCESS:EXIT_FAILURE; + + fclose(f); + return (res==ntests)?EXIT_SUCCESS:EXIT_FAILURE; } int main(int argc, char * argv[]) { - // fprintf(stdout, "%s Version %d.%d\n", argv[0], JPSCORE_MINOR_VERSION, JPSCORE_MAJOR_VERSION); - return testIsInside(); + // fprintf(stdout, "%s Version %d.%d\n", argv[0], JPSCORE_MINOR_VERSION, JPSCORE_MAJOR_VERSION); + return testIsInside(); } diff --git a/Utest/testIsOn.cpp b/Utest/testIsOn.cpp index 9c450f7eb02f91afbec30316544cf33ef1b9f6a6..2e1a2fb9c3bc17ddfbd7ae06657f337dc4fad8d3 100644 --- a/Utest/testIsOn.cpp +++ b/Utest/testIsOn.cpp @@ -6,11 +6,11 @@ #ifdef WINDOWS #include <direct.h> - #define GetCurrentDir _getcwd +#define GetCurrentDir _getcwd #else #include <unistd.h> - #define GetCurrentDir getcwd - #endif +#define GetCurrentDir getcwd +#endif OutputHandler* Log; @@ -19,124 +19,123 @@ OutputHandler* Log; int testIsOn() { - char cCurrentPath[FILENAME_MAX]; - if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) - { - return EXIT_FAILURE; - } - cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ - - FILE * f; - char fname[FILENAME_MAX] = "log_testIsOn.txt"; - // strcpy(fname, cCurrentPath); - // strcat(fname, "logs/log_testPointOnEllipse.txt"); - f = fopen(fname, "w"); - fprintf (f, "The current working directory is %s\n\n", cCurrentPath); - int ntests=0, res=0; - float a=2.0, b=5.0; - JEllipse E; - Point P; - double px, py; - E.SetCenter( Point(0,0) ); - E.SetV0(1); - E.SetV( Point(0,0) ); - E.SetAmin(a); - E.SetBmax(b); - // P == E.center - P.SetX(0); - P.SetY(0); - res += ( E.IsOn(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%-4.2f, %-4.2f), a=%-4.2f, b=%-4.2f, P(%4.2f, %4.2f) res=%-3d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - // P ~ E.center - - P.SetX(0.); - P.SetY(-0.3); - res += ( E.IsOn(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%-4.2f, %-4.2f), a=%-4.2f, b=%-4.2f, P(%4.2f, %4.2f) res=%-3d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - // P ~ E.center - P.SetX(-0.73); - P.SetY(-0.3); - res += ( E.IsOn(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - // P semi-axis - P.SetX(a); - P.SetY(0); - res += ( E.IsOn(P) == true)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - // P semi-axis - P.SetX(-a); - P.SetY(0); - res += ( E.IsOn(P) == true)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - // P ~ semi-axis - P.SetX(0); - P.SetY(b); - res += ( E.IsOn(P) == true)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - // P ~ semi-axis - P.SetX(0); - P.SetY(-b); - res += ( E.IsOn(P) == true)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - // P outside - P.SetX(a); - P.SetY(-b); - res += ( E.IsOn(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - // P outside - P.SetX(2*a); - P.SetY(3.1*b); - res += ( E.IsOn(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - - // P outside - P.SetX(3*a); - P.SetY(-3.5*b); - res += ( E.IsOn(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - - // P outside - P.SetX(-5*a); - P.SetY(-2*b); - res += ( E.IsOn(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - - // P outside - P.SetX(-1.1*a); - P.SetY(-1.1*b); - res += ( E.IsOn(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + char cCurrentPath[FILENAME_MAX]; + if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) { + return EXIT_FAILURE; + } + cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ + + FILE * f; + char fname[FILENAME_MAX] = "log_testIsOn.txt"; + // strcpy(fname, cCurrentPath); + // strcat(fname, "logs/log_testPointOnEllipse.txt"); + f = fopen(fname, "w"); + fprintf (f, "The current working directory is %s\n\n", cCurrentPath); + int ntests=0, res=0; + float a=2.0, b=5.0; + JEllipse E; + Point P; + double px, py; + E.SetCenter( Point(0,0) ); + E.SetV0(1); + E.SetV( Point(0,0) ); + E.SetAmin(a); + E.SetBmax(b); + // P == E.center + P.SetX(0); + P.SetY(0); + res += ( E.IsOn(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%-4.2f, %-4.2f), a=%-4.2f, b=%-4.2f, P(%4.2f, %4.2f) res=%-3d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + // P ~ E.center + + P.SetX(0.); + P.SetY(-0.3); + res += ( E.IsOn(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%-4.2f, %-4.2f), a=%-4.2f, b=%-4.2f, P(%4.2f, %4.2f) res=%-3d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + // P ~ E.center + P.SetX(-0.73); + P.SetY(-0.3); + res += ( E.IsOn(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + // P semi-axis + P.SetX(a); + P.SetY(0); + res += ( E.IsOn(P) == true)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + // P semi-axis + P.SetX(-a); + P.SetY(0); + res += ( E.IsOn(P) == true)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + // P ~ semi-axis + P.SetX(0); + P.SetY(b); + res += ( E.IsOn(P) == true)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + // P ~ semi-axis + P.SetX(0); + P.SetY(-b); + res += ( E.IsOn(P) == true)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + // P outside + P.SetX(a); + P.SetY(-b); + res += ( E.IsOn(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + +// P outside + P.SetX(2*a); + P.SetY(3.1*b); + res += ( E.IsOn(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + +// P outside + P.SetX(3*a); + P.SetY(-3.5*b); + res += ( E.IsOn(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + +// P outside + P.SetX(-5*a); + P.SetY(-2*b); + res += ( E.IsOn(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + +// P outside + P.SetX(-1.1*a); + P.SetY(-1.1*b); + res += ( E.IsOn(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); //----------------------------------------------------------------- - - fclose(f); - return (res==ntests)?EXIT_SUCCESS:EXIT_FAILURE; + + fclose(f); + return (res==ntests)?EXIT_SUCCESS:EXIT_FAILURE; } int main(int argc, char * argv[]) { - // fprintf(stdout, "%s Version %d.%d\n", argv[0], JPSCORE_MINOR_VERSION, JPSCORE_MAJOR_VERSION); - return testIsOn(); + // fprintf(stdout, "%s Version %d.%d\n", argv[0], JPSCORE_MINOR_VERSION, JPSCORE_MAJOR_VERSION); + return testIsOn(); } diff --git a/Utest/testIsOutside.cpp b/Utest/testIsOutside.cpp index 048e5b06d47e75496dd73536b361c290488c369a..908882d74e53ed0905421d6e1659877ffa37bf10 100644 --- a/Utest/testIsOutside.cpp +++ b/Utest/testIsOutside.cpp @@ -6,11 +6,11 @@ #ifdef WINDOWS #include <direct.h> - #define GetCurrentDir _getcwd +#define GetCurrentDir _getcwd #else #include <unistd.h> - #define GetCurrentDir getcwd - #endif +#define GetCurrentDir getcwd +#endif OutputHandler* Log; @@ -19,124 +19,123 @@ OutputHandler* Log; int testIsOutside() { - char cCurrentPath[FILENAME_MAX]; - if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) - { - return EXIT_FAILURE; - } - cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ - - FILE * f; - char fname[FILENAME_MAX] = "log_testIsOutside.txt"; - // strcpy(fname, cCurrentPath); - // strcat(fname, "logs/log_testPointOnEllipse.txt"); - f = fopen(fname, "w"); - fprintf (f, "The current working directory is %s\n\n", cCurrentPath); - int ntests=0, res=0; - float a=2.0, b=5.0; - JEllipse E; - Point P; - //double px, py; - E.SetCenter( Point(0,0) ); - E.SetV0(1); - E.SetV( Point(0,0) ); - E.SetAmin(a); - E.SetBmax(b); - // P == E.center - P.SetX(0); - P.SetY(0); - res += ( E.IsOutside(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%-4.2f, %-4.2f), a=%-4.2f, b=%-4.2f, P(%4.2f, %4.2f) res=%-3d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - // P ~ E.center - - P.SetX(0.); - P.SetY(-0.3); - res += ( E.IsOutside(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%-4.2f, %-4.2f), a=%-4.2f, b=%-4.2f, P(%4.2f, %4.2f) res=%-3d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - // P ~ E.center - P.SetX(-0.73); - P.SetY(-0.3); - res += ( E.IsOutside(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - // P semi-axis - P.SetX(a); - P.SetY(0); - res += ( E.IsOutside(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - // P semi-axis - P.SetX(-a); - P.SetY(0); - res += ( E.IsOutside(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - // P ~ semi-axis - P.SetX(0); - P.SetY(b); - res += ( E.IsOutside(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - // P ~ semi-axis - P.SetX(0); - P.SetY(-b); - res += ( E.IsOutside(P) == false)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - // P outside - P.SetX(a); - P.SetY(-b); - res += ( E.IsOutside(P) == true)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - // P outside - P.SetX(2*a); - P.SetY(3.1*b); - res += ( E.IsOutside(P) == true)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - - // P outside - P.SetX(3*a); - P.SetY(-3.5*b); - res += ( E.IsOutside(P) == true)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - - // P outside - P.SetX(-5*a); - P.SetY(-2*b); - res += ( E.IsOutside(P) == true)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); - - - // P outside - P.SetX(-1.1*a); - P.SetY(-1.1*b); - res += ( E.IsOutside(P) == true)?1:0; - ntests++; - fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + char cCurrentPath[FILENAME_MAX]; + if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) { + return EXIT_FAILURE; + } + cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ + + FILE * f; + char fname[FILENAME_MAX] = "log_testIsOutside.txt"; + // strcpy(fname, cCurrentPath); + // strcat(fname, "logs/log_testPointOnEllipse.txt"); + f = fopen(fname, "w"); + fprintf (f, "The current working directory is %s\n\n", cCurrentPath); + int ntests=0, res=0; + float a=2.0, b=5.0; + JEllipse E; + Point P; + //double px, py; + E.SetCenter( Point(0,0) ); + E.SetV0(1); + E.SetV( Point(0,0) ); + E.SetAmin(a); + E.SetBmax(b); + // P == E.center + P.SetX(0); + P.SetY(0); + res += ( E.IsOutside(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%-4.2f, %-4.2f), a=%-4.2f, b=%-4.2f, P(%4.2f, %4.2f) res=%-3d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + // P ~ E.center + + P.SetX(0.); + P.SetY(-0.3); + res += ( E.IsOutside(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%-4.2f, %-4.2f), a=%-4.2f, b=%-4.2f, P(%4.2f, %4.2f) res=%-3d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + // P ~ E.center + P.SetX(-0.73); + P.SetY(-0.3); + res += ( E.IsOutside(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + // P semi-axis + P.SetX(a); + P.SetY(0); + res += ( E.IsOutside(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + // P semi-axis + P.SetX(-a); + P.SetY(0); + res += ( E.IsOutside(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + // P ~ semi-axis + P.SetX(0); + P.SetY(b); + res += ( E.IsOutside(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + // P ~ semi-axis + P.SetX(0); + P.SetY(-b); + res += ( E.IsOutside(P) == false)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + // P outside + P.SetX(a); + P.SetY(-b); + res += ( E.IsOutside(P) == true)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + +// P outside + P.SetX(2*a); + P.SetY(3.1*b); + res += ( E.IsOutside(P) == true)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + +// P outside + P.SetX(3*a); + P.SetY(-3.5*b); + res += ( E.IsOutside(P) == true)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + +// P outside + P.SetX(-5*a); + P.SetY(-2*b); + res += ( E.IsOutside(P) == true)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); + + +// P outside + P.SetX(-1.1*a); + P.SetY(-1.1*b); + res += ( E.IsOutside(P) == true)?1:0; + ntests++; + fprintf (f, "%3d. E(%3.2f, %3.2f), a=%3.2f, b=%3.2f, P(%3.2f, %3.2f) res=%d\n",ntests, E.GetCenter().GetX(), E.GetCenter().GetY(), a, b, P.GetX(), P.GetY(), res); //----------------------------------------------------------------- - - fclose(f); - return (res==ntests)?EXIT_SUCCESS:EXIT_FAILURE; + + fclose(f); + return (res==ntests)?EXIT_SUCCESS:EXIT_FAILURE; } int main(int argc, char * argv[]) { - // fprintf(stdout, "%s Version %d.%d\n", argv[0], JPSCORE_MINOR_VERSION, JPSCORE_MAJOR_VERSION); - return testIsOutside(); + // fprintf(stdout, "%s Version %d.%d\n", argv[0], JPSCORE_MINOR_VERSION, JPSCORE_MAJOR_VERSION); + return testIsOutside(); } diff --git a/Utest/testPointOnEllipse.cpp b/Utest/testPointOnEllipse.cpp index 3d90123effe05a0806173017f5e2c28c62c20263..a994f79f1a4a0fc935e57cb052b12f86ca549c1f 100644 --- a/Utest/testPointOnEllipse.cpp +++ b/Utest/testPointOnEllipse.cpp @@ -6,11 +6,11 @@ #ifdef WINDOWS #include <direct.h> - #define GetCurrentDir _getcwd +#define GetCurrentDir _getcwd #else #include <unistd.h> - #define GetCurrentDir getcwd - #endif +#define GetCurrentDir getcwd +#endif //OutputHandler* Log; @@ -19,84 +19,82 @@ int testPointOnEllipse() { - char cCurrentPath[FILENAME_MAX]; - if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) - { - return EXIT_FAILURE; - } - cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ + char cCurrentPath[FILENAME_MAX]; + if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) { + return EXIT_FAILURE; + } + cCurrentPath[sizeof(cCurrentPath) - 1] = '\0'; /* not really required */ - FILE * f; - char fname[FILENAME_MAX] = "log_testPointOnEllipse.txt"; - // strcpy(fname, cCurrentPath); - // strcat(fname, "logs/log_testPointOnEllipse.txt"); - f = fopen(fname, "w"); - fprintf (f, "The current working directory is %s\n\n", cCurrentPath); - int i, j, ntests=0, res=0; - float r=2.0; - JEllipse E; - E.SetCenter( Point(0,0) ); - E.SetV0(1); - E.SetV( Point(0,0) ); - E.SetAmin(r); - E.SetBmax(r); - - float sx, sy, l; - Point S(0,0); //test point - Point P(0,0); // result - Point T(0,0); // should be result + FILE * f; + char fname[FILENAME_MAX] = "log_testPointOnEllipse.txt"; + // strcpy(fname, cCurrentPath); + // strcat(fname, "logs/log_testPointOnEllipse.txt"); + f = fopen(fname, "w"); + fprintf (f, "The current working directory is %s\n\n", cCurrentPath); + int i, j, ntests=0, res=0; + float r=2.0; + JEllipse E; + E.SetCenter( Point(0,0) ); + E.SetV0(1); + E.SetV( Point(0,0) ); + E.SetAmin(r); + E.SetBmax(r); - for (i=0;i<2;i++) - for (j=0;j<2;j++) - { - if(!(i|j)) continue; - sx = i*r; - sy = j*r; - S.SetX(sx); - S.SetY(sy); - l = S.Norm(); - T.SetX(r*sx/l); - T.SetY(r*sy/l); - P = E.PointOnEllipse(S); - res += (P==T)?1:0; - ntests++; - fprintf (f, "%d. Tx=%.2f\t Ty=%.2f\t Px=%.2f\t Py=%.2f\t res=%d\t\n",ntests, T.GetX(), T.GetY(), P.GetX(), P.GetY(), res); - } + float sx, sy, l; + Point S(0,0); //test point + Point P(0,0); // result + Point T(0,0); // should be result - // test point in the ellipse - sx = 0.5*r; - sy = 0.5*r; - S.SetX(sx); - S.SetY(sy); - l = S.Norm(); - T.SetX(r*sx/l); - T.SetY(r*sy/l); - P = E.PointOnEllipse(S); - res += (P==T)?1:0; - ntests++; - fprintf (f, "%d. Tx=%.2f\t Ty=%.2f\t Px=%.2f\t Py=%.2f\t res=%d\t\n",ntests, T.GetX(), T.GetY(), P.GetX(), P.GetY(), res); - // point in the center + for (i=0; i<2; i++) + for (j=0; j<2; j++) { + if(!(i|j)) continue; + sx = i*r; + sy = j*r; + S.SetX(sx); + S.SetY(sy); + l = S.Norm(); + T.SetX(r*sx/l); + T.SetY(r*sy/l); + P = E.PointOnEllipse(S); + res += (P==T)?1:0; + ntests++; + fprintf (f, "%d. Tx=%.2f\t Ty=%.2f\t Px=%.2f\t Py=%.2f\t res=%d\t\n",ntests, T.GetX(), T.GetY(), P.GetX(), P.GetY(), res); + } - sx = 0; - sy = 0; - S.SetX(sx); - S.SetY(sy); + // test point in the ellipse + sx = 0.5*r; + sy = 0.5*r; + S.SetX(sx); + S.SetY(sy); + l = S.Norm(); + T.SetX(r*sx/l); + T.SetY(r*sy/l); + P = E.PointOnEllipse(S); + res += (P==T)?1:0; + ntests++; + fprintf (f, "%d. Tx=%.2f\t Ty=%.2f\t Px=%.2f\t Py=%.2f\t res=%d\t\n",ntests, T.GetX(), T.GetY(), P.GetX(), P.GetY(), res); + // point in the center + + sx = 0; + sy = 0; + S.SetX(sx); + S.SetY(sy); // T.SetX(0); - // T.SetY(0); - E.SetCenter( Point(0.4, 1.78) ); - T = E.GetCenter() + Point(r,0); - P = E.PointOnEllipse(S); - res += (P==T)?1:0; - ntests++; - fprintf (f, "%d. Tx=%.2f\t Ty=%.2f\t Px=%.2f\t Py=%.2f\t res=%d\t\n",ntests, T.GetX(), T.GetY(), P.GetX(), P.GetY(), res); - - fclose(f); - return (res==ntests)?EXIT_SUCCESS:EXIT_FAILURE; + // T.SetY(0); + E.SetCenter( Point(0.4, 1.78) ); + T = E.GetCenter() + Point(r,0); + P = E.PointOnEllipse(S); + res += (P==T)?1:0; + ntests++; + fprintf (f, "%d. Tx=%.2f\t Ty=%.2f\t Px=%.2f\t Py=%.2f\t res=%d\t\n",ntests, T.GetX(), T.GetY(), P.GetX(), P.GetY(), res); + + fclose(f); + return (res==ntests)?EXIT_SUCCESS:EXIT_FAILURE; } int main() { - // fprintf(stdout, "%s Version %d.%d\n", argv[0], JPSCORE_MINOR_VERSION, JPSCORE_MAJOR_VERSION); - return testPointOnEllipse(); + // fprintf(stdout, "%s Version %d.%d\n", argv[0], JPSCORE_MINOR_VERSION, JPSCORE_MAJOR_VERSION); + return testPointOnEllipse(); } diff --git a/Utest/testSign.cpp b/Utest/testSign.cpp index 806f5d033e519df3b62db966daf96e45e00464a1..9d164078ef925562ce786c0d5459de5f34f70382 100644 --- a/Utest/testSign.cpp +++ b/Utest/testSign.cpp @@ -3,10 +3,10 @@ // test positive number int testSign() { - return (sign(1.0)==1)?EXIT_SUCCESS:EXIT_FAILURE; + return (sign(1.0)==1)?EXIT_SUCCESS:EXIT_FAILURE; } int main() { - return testSign(); + return testSign(); } diff --git a/Utest/testSign1.cpp b/Utest/testSign1.cpp index 132925c0ff414e658d98bd61caa4611600836152..e685eb60e056de54498c058455e7530e141b2e91 100644 --- a/Utest/testSign1.cpp +++ b/Utest/testSign1.cpp @@ -2,11 +2,12 @@ #include "../math/Mathematics.h" // test negative number -int testSign1(){ - return (sign(-1.0)==-1)?EXIT_SUCCESS:EXIT_FAILURE; +int testSign1() +{ + return (sign(-1.0)==-1)?EXIT_SUCCESS:EXIT_FAILURE; } int main() { - return testSign1(); + return testSign1(); } diff --git a/Utest/testequal.cpp b/Utest/testequal.cpp index 1b4f0cc0eb3e114b49f0124339a10cb571e455ae..5b8004da78d2ccd7ec2be223879ec90a5035c827 100644 --- a/Utest/testequal.cpp +++ b/Utest/testequal.cpp @@ -1,4 +1,4 @@ -// Test Equal.GetRand() +// Test Equal.GetRand() #include <cstdlib> #include "../math/Distribution.h" #include <stdio.h> @@ -6,39 +6,39 @@ //x should be in [mu-sigma, mu+sigma] int test_equal() { - FILE * f; - char fname[FILENAME_MAX] = "log_testEqual.txt"; - f = fopen(fname, "w"); + FILE * f; + char fname[FILENAME_MAX] = "log_testEqual.txt"; + f = fopen(fname, "w"); - int res = 0; - double mu = 1.24; - double sigma = 0.26; - double r; - // test different constructors - // 1 - Equal distequal(mu, sigma); - r = distequal.GetRand(); - res = ( r < mu-sigma || mu+sigma < r )?0:1; - fprintf(f, "1: mu=%.2f\t sigma=%.2f\t [%.2f, %.2f]\t r=%.2f\t res=%d\n",mu, sigma, mu-sigma, mu+sigma, r, res); - // 2 - Equal distequal1(distequal); - r = distequal.GetRand(); - res += (distequal.GetRand()< mu-sigma || mu+sigma<distequal.GetRand())?0:1; - fprintf(f, "2: mu=%.2f\t sigma=%.2f\t [%.2f, %.2f]\t r=%.2f\t res=%d\n",mu, sigma, mu-sigma, mu+sigma, r, res); - // 3 - Equal distequal2(); - r = distequal.GetRand(); - res += (distequal.GetRand()< mu-sigma || mu+sigma<distequal.GetRand())?0:1; - fprintf(f, "3: mu=%.2f\t sigma=%.2f\t [%.2f, %.2f]\t r=%.2f\t res=%d\n",mu, sigma, mu-sigma, mu+sigma, r, res); - + int res = 0; + double mu = 1.24; + double sigma = 0.26; + double r; + // test different constructors + // 1 + Equal distequal(mu, sigma); + r = distequal.GetRand(); + res = ( r < mu-sigma || mu+sigma < r )?0:1; + fprintf(f, "1: mu=%.2f\t sigma=%.2f\t [%.2f, %.2f]\t r=%.2f\t res=%d\n",mu, sigma, mu-sigma, mu+sigma, r, res); + // 2 + Equal distequal1(distequal); + r = distequal.GetRand(); + res += (distequal.GetRand()< mu-sigma || mu+sigma<distequal.GetRand())?0:1; + fprintf(f, "2: mu=%.2f\t sigma=%.2f\t [%.2f, %.2f]\t r=%.2f\t res=%d\n",mu, sigma, mu-sigma, mu+sigma, r, res); + // 3 + Equal distequal2(); + r = distequal.GetRand(); + res += (distequal.GetRand()< mu-sigma || mu+sigma<distequal.GetRand())?0:1; + fprintf(f, "3: mu=%.2f\t sigma=%.2f\t [%.2f, %.2f]\t r=%.2f\t res=%d\n",mu, sigma, mu-sigma, mu+sigma, r, res); - fclose(f); - return (res!=3)?EXIT_FAILURE:EXIT_SUCCESS; + + fclose(f); + return (res!=3)?EXIT_FAILURE:EXIT_SUCCESS; } int main() { - return test_equal(); + return test_equal(); } diff --git a/events/EventManager.cpp b/events/EventManager.cpp index b44c0cb8fa81bd3d3a19444d5c29372b7fc628c4..8a3e8591e2cd07c4b60bb3baf700f600ebc369f7 100644 --- a/events/EventManager.cpp +++ b/events/EventManager.cpp @@ -6,255 +6,253 @@ using namespace std; Konstruktoren ******************/ -EventManager::EventManager(Building *_b){ - _event_times=vector<double>(); - _event_types=vector<string>(); - _event_states=vector<string>(); - _event_ids=vector<int>(); - _projectFilename = ""; - _building = _b; - _deltaT=NULL; - _eventCounter=0; - _dynamic=false; - _file = fopen("../events/events.txt","r"); - if(!_file){ - Log->Write("INFO:\tDatei events.txt nicht gefunden. Dynamisches Eventhandling nicht moeglich."); - } - else{ - Log->Write("INFO:\tDatei events.txt gefunden. Dynamisches Eventhandling moeglich."); - _dynamic=true; - } +EventManager::EventManager(Building *_b) +{ + _event_times=vector<double>(); + _event_types=vector<string>(); + _event_states=vector<string>(); + _event_ids=vector<int>(); + _projectFilename = ""; + _building = _b; + _deltaT=NULL; + _eventCounter=0; + _dynamic=false; + _file = fopen("../events/events.txt","r"); + if(!_file) { + Log->Write("INFO:\tDatei events.txt nicht gefunden. Dynamisches Eventhandling nicht moeglich."); + } else { + Log->Write("INFO:\tDatei events.txt gefunden. Dynamisches Eventhandling moeglich."); + _dynamic=true; + } } /******************* Dateien einlesen ******************/ -void EventManager::SetProjectFilename(const std::string &filename){ - _projectFilename=filename; +void EventManager::SetProjectFilename(const std::string &filename) +{ + _projectFilename=filename; } -void EventManager::SetProjectRootDir(const std::string &filename){ - _projectRootDir= filename; +void EventManager::SetProjectRootDir(const std::string &filename) +{ + _projectRootDir= filename; } -void EventManager::readEventsXml(){ - Log->Write("INFO: \tReading events\n "); - //get the geometry filename from the project file - TiXmlDocument doc(_projectFilename); - if (!doc.LoadFile()){ - Log->Write("ERROR: \t%s", doc.ErrorDesc()); - Log->Write("ERROR: \t could not parse the project file. "); - exit(EXIT_FAILURE); - } +void EventManager::readEventsXml() +{ + Log->Write("INFO: \tReading events\n "); + //get the geometry filename from the project file + TiXmlDocument doc(_projectFilename); + if (!doc.LoadFile()) { + Log->Write("ERROR: \t%s", doc.ErrorDesc()); + Log->Write("ERROR: \t could not parse the project file. "); + exit(EXIT_FAILURE); + } - Log->Write("INFO: \tParsing the event file"); - TiXmlElement* xMainNode = doc.RootElement(); - string eventfile=""; - if(xMainNode->FirstChild("events")){ - eventfile=_projectRootDir+xMainNode->FirstChild("events")->FirstChild()->Value(); - Log->Write("INFO: \tevents <"+eventfile+">"); - } + Log->Write("INFO: \tParsing the event file"); + TiXmlElement* xMainNode = doc.RootElement(); + string eventfile=""; + if(xMainNode->FirstChild("events")) { + eventfile=_projectRootDir+xMainNode->FirstChild("events")->FirstChild()->Value(); + Log->Write("INFO: \tevents <"+eventfile+">"); + } - TiXmlDocument docEvent(eventfile); - if(!docEvent.LoadFile()){ - Log->Write("INFO: \t%s",docEvent.ErrorDesc()); - Log->Write("INFO: \t could not parse the event file. So no Events are found."); - //exit(EXIT_FAILURE); - return; - } + TiXmlDocument docEvent(eventfile); + if(!docEvent.LoadFile()) { + Log->Write("INFO: \t%s",docEvent.ErrorDesc()); + Log->Write("INFO: \t could not parse the event file. So no Events are found."); + //exit(EXIT_FAILURE); + return; + } - TiXmlElement* xRootNode = docEvent.RootElement(); - if(!xRootNode){ - Log->Write("ERROR:\tRoot element does not exist."); - exit(EXIT_FAILURE); - } + TiXmlElement* xRootNode = docEvent.RootElement(); + if(!xRootNode) { + Log->Write("ERROR:\tRoot element does not exist."); + exit(EXIT_FAILURE); + } - if( xRootNode->ValueStr () != "JPScore" ) { - Log->Write("ERROR:\tRoot element value is not 'JPScore'."); - exit(EXIT_FAILURE); - } + if( xRootNode->ValueStr () != "JPScore" ) { + Log->Write("ERROR:\tRoot element value is not 'JPScore'."); + exit(EXIT_FAILURE); + } - TiXmlNode* xEvents = xRootNode->FirstChild("events"); - if(!xEvents){ - Log->Write("ERROR:\tNo events found."); - exit(EXIT_FAILURE); - } - - for(TiXmlElement* e = xEvents->FirstChildElement("event"); e; e= e->NextSiblingElement("event")){ - _event_times.push_back(atoi(e->Attribute("time"))); - _event_types.push_back(e->Attribute("type")); - _event_states.push_back(e->Attribute("state")); - _event_ids.push_back(atoi(e->Attribute("id"))); - } - Log->Write("INFO: \tEvents were read\n"); + TiXmlNode* xEvents = xRootNode->FirstChild("events"); + if(!xEvents) { + Log->Write("ERROR:\tNo events found."); + exit(EXIT_FAILURE); + } + + for(TiXmlElement* e = xEvents->FirstChildElement("event"); e; e= e->NextSiblingElement("event")) { + _event_times.push_back(atoi(e->Attribute("time"))); + _event_types.push_back(e->Attribute("type")); + _event_states.push_back(e->Attribute("state")); + _event_ids.push_back(atoi(e->Attribute("id"))); + } + Log->Write("INFO: \tEvents were read\n"); } -void EventManager::listEvents(){ - if(_event_times.size()==0){ - Log->Write("INFO: \tNo events in the events.xml"); - } - else{ - int i; - char buf[10],buf2[10]; - for(i=0;i<_event_times.size();i++){ - sprintf(buf,"%f",_event_times[i]); - sprintf(buf2,"%d",_event_ids[i]); - Log->Write("INFO: \tAfter "+string(buf)+" sec: "+_event_types[i]+" "+string(buf2)+" "+_event_states[i]); - } - } +void EventManager::listEvents() +{ + if(_event_times.size()==0) { + Log->Write("INFO: \tNo events in the events.xml"); + } else { + int i; + char buf[10],buf2[10]; + for(i=0; i<_event_times.size(); i++) { + sprintf(buf,"%f",_event_times[i]); + sprintf(buf2,"%d",_event_ids[i]); + Log->Write("INFO: \tAfter "+string(buf)+" sec: "+_event_types[i]+" "+string(buf2)+" "+_event_states[i]); + } + } } -void EventManager::readEventsTxt(double time){ - rewind(_file); - char cstring[256]; - int lines=0; - do{ - fgets(cstring,30,_file); - if(cstring[0]!='#'){// keine Kommentarzeile - lines++; - if(lines>_eventCounter){ - Log->Write("INFO:\tEvent: after %f sec: ",time); - getTheEvent(cstring); - _eventCounter++; - } - } - }while (feof(_file)==0); +void EventManager::readEventsTxt(double time) +{ + rewind(_file); + char cstring[256]; + int lines=0; + do { + fgets(cstring,30,_file); + if(cstring[0]!='#') { // keine Kommentarzeile + lines++; + if(lines>_eventCounter) { + Log->Write("INFO:\tEvent: after %f sec: ",time); + getTheEvent(cstring); + _eventCounter++; + } + } + } while (feof(_file)==0); } /*********** Update **********/ -void EventManager::Update_Events(double time, double d){ - //1. pruefen ob in _event_times der zeitstempel time zu finden ist. Wenn ja zu 2. sonst zu 3. - //2. Event aus _event_times und _event_values verarbeiten (Tuere schliessen/oeffnen, neues Routing) - // Dann pruefen, ob eine neue Zeile in der .txt Datei steht - //3. .txt Datei auf neue Zeilen pruefen. Wenn es neue gibt diese Events verarbeiten ( Tuere schliessen/oeffnen, - // neues Routing) ansonsten fertig +void EventManager::Update_Events(double time, double d) +{ + //1. pruefen ob in _event_times der zeitstempel time zu finden ist. Wenn ja zu 2. sonst zu 3. + //2. Event aus _event_times und _event_values verarbeiten (Tuere schliessen/oeffnen, neues Routing) + // Dann pruefen, ob eine neue Zeile in der .txt Datei steht + //3. .txt Datei auf neue Zeilen pruefen. Wenn es neue gibt diese Events verarbeiten ( Tuere schliessen/oeffnen, + // neues Routing) ansonsten fertig - //zuerst muss die Reroutingzeit der Peds aktualisiert werden: - _deltaT=d; - vector<Pedestrian*> _allPedestrians=_building->GetAllPedestrians(); - int nSize = _allPedestrians.size(); - for(int p=0;p<nSize;p++){ - _allPedestrians[p]->UpdateReroutingTime(); - if(_allPedestrians[p]->IsReadyForRerouting()){ - _allPedestrians[p]->ClearMentalMap(); - _allPedestrians[p]->ResetRerouting(); - } - } - int i; - for(i=0;i<_event_times.size();i++){ - if(fabs(_event_times[i]-time)<0.0000001){ - //Event findet statt - Log->Write("INFO:\tEvent: after %f sec: ",time); - if(_event_states[i].compare("close")==0){ - closeDoor(_event_ids[i]); - } - else{ - openDoor(_event_ids[i]); - } - } - } - if(_dynamic) - readEventsTxt(time); + //zuerst muss die Reroutingzeit der Peds aktualisiert werden: + _deltaT=d; + vector<Pedestrian*> _allPedestrians=_building->GetAllPedestrians(); + int nSize = _allPedestrians.size(); + for(int p=0; p<nSize; p++) { + _allPedestrians[p]->UpdateReroutingTime(); + if(_allPedestrians[p]->IsReadyForRerouting()) { + _allPedestrians[p]->ClearMentalMap(); + _allPedestrians[p]->ResetRerouting(); + } + } + int i; + for(i=0; i<_event_times.size(); i++) { + if(fabs(_event_times[i]-time)<0.0000001) { + //Event findet statt + Log->Write("INFO:\tEvent: after %f sec: ",time); + if(_event_states[i].compare("close")==0) { + closeDoor(_event_ids[i]); + } else { + openDoor(_event_ids[i]); + } + } + } + if(_dynamic) + readEventsTxt(time); } /*************** Eventhandling **************/ -void EventManager::closeDoor(int id){ - //pruefen ob entsprechende Tuer schon zu ist, wenn nicht dann schliessen und neues Routing berechnen - Transition *t=_building->GetTransition(id); - if(t->IsOpen()){ - t->Close(); - Log->Write("\tDoor %d closed.",id); - changeRouting(id,"close"); - } - else{ - Log->Write("Door %d is already close yet.", id); - } +void EventManager::closeDoor(int id) +{ + //pruefen ob entsprechende Tuer schon zu ist, wenn nicht dann schliessen und neues Routing berechnen + Transition *t=_building->GetTransition(id); + if(t->IsOpen()) { + t->Close(); + Log->Write("\tDoor %d closed.",id); + changeRouting(id,"close"); + } else { + Log->Write("Door %d is already close yet.", id); + } } -void EventManager::openDoor(int id){ - //pruefen ob entsprechende Tuer schon offen ist, wenn nicht dann oeffnen und neues Routing berechnen - Transition *t=_building->GetTransition(id); - if(!t->IsOpen()){ - t->Open(); - Log->Write("\tDoor %d opened.",id); - changeRouting(id,"open"); - } - else{ - Log->Write("Door %d is already open yet.", id); - } +void EventManager::openDoor(int id) +{ + //pruefen ob entsprechende Tuer schon offen ist, wenn nicht dann oeffnen und neues Routing berechnen + Transition *t=_building->GetTransition(id); + if(!t->IsOpen()) { + t->Open(); + Log->Write("\tDoor %d opened.",id); + changeRouting(id,"open"); + } else { + Log->Write("Door %d is already open yet.", id); + } } -void EventManager::changeRouting(int id, string state){ - RoutingEngine* routingEngine= _building->GetRoutingEngine(); - routingEngine->Init(_building); - _building->InitPhiAllPeds(_deltaT); - vector<Pedestrian*> _allPedestrians=_building->GetAllPedestrians(); - unsigned int nSize = _allPedestrians.size(); +void EventManager::changeRouting(int id, string state) +{ + RoutingEngine* routingEngine= _building->GetRoutingEngine(); + routingEngine->Init(_building); + _building->InitPhiAllPeds(_deltaT); + vector<Pedestrian*> _allPedestrians=_building->GetAllPedestrians(); + unsigned int nSize = _allPedestrians.size(); - //Pedestrians sollen, damit es realitaetsnaeher wird, je nachdem wo sie stehen erst spaeter merken, - //dass sich Tueren aendern. - Transition *t = _building->GetTransition(id); - //Abstand der aktuellen Position des Pedestrians zur entsprechenden Tuer: Tuer als Linie sehen und mit - //DistTo(ped.GetPos()) den Abstand messen - Line* l = new Line(t->GetPoint1(),t->GetPoint2()); - for (int p = 0; p < nSize; ++p) { - //if(_allPedestrians[p]->GetExitIndex()==t->GetUniqueID()){ - double dist = l->DistTo(_allPedestrians[p]->GetPos()); - if(dist>0.0&&dist<0.5){ - _allPedestrians[p]->ClearMentalMap(); - } - else if(dist>=0.5&&dist<3.0){ - _allPedestrians[p]->RerouteIn(1.0); - } - else{ - _allPedestrians[p]->RerouteIn(2.0); - } - //} - //else{ + //Pedestrians sollen, damit es realitaetsnaeher wird, je nachdem wo sie stehen erst spaeter merken, + //dass sich Tueren aendern. + Transition *t = _building->GetTransition(id); + //Abstand der aktuellen Position des Pedestrians zur entsprechenden Tuer: Tuer als Linie sehen und mit + //DistTo(ped.GetPos()) den Abstand messen + Line* l = new Line(t->GetPoint1(),t->GetPoint2()); + for (int p = 0; p < nSize; ++p) { + //if(_allPedestrians[p]->GetExitIndex()==t->GetUniqueID()){ + double dist = l->DistTo(_allPedestrians[p]->GetPos()); + if(dist>0.0&&dist<0.5) { + _allPedestrians[p]->ClearMentalMap(); + } else if(dist>=0.5&&dist<3.0) { + _allPedestrians[p]->RerouteIn(1.0); + } else { + _allPedestrians[p]->RerouteIn(2.0); + } + //} + //else{ // _allPedestrians[p]->ClearMentalMap(); - //} - } + //} + } } -void EventManager::getTheEvent(char* c){ - int split = 0; - string type = ""; - string id = ""; - string state = ""; - for(int i=0;i<20;i++){ - if(c[i]==NULL){ - break; - } - else if(c[i]==' '){ - split++; - } - else if(c[i]=='\n'){ +void EventManager::getTheEvent(char* c) +{ + int split = 0; + string type = ""; + string id = ""; + string state = ""; + for(int i=0; i<20; i++) { + if(c[i]==NULL) { + break; + } else if(c[i]==' ') { + split++; + } else if(c[i]=='\n') { - } - else{ - if(split==0){ - type+=c[i]; - } - else if(split==1){ - id+=c[i]; - } - else if(split==2){ - state+=c[i]; - } - } + } else { + if(split==0) { + type+=c[i]; + } else if(split==1) { + id+=c[i]; + } else if(split==2) { + state+=c[i]; + } + } - } - if(state.compare("close")==0){ - closeDoor(atoi(id.c_str())); - } - else{ - openDoor(atoi(id.c_str())); - } + } + if(state.compare("close")==0) { + closeDoor(atoi(id.c_str())); + } else { + openDoor(atoi(id.c_str())); + } } diff --git a/events/EventManager.h b/events/EventManager.h index f8df1588a719012a24f83ec7a85665b876500431..16c2d5161488f291b8be540b14a4e1ba757f573f 100644 --- a/events/EventManager.h +++ b/events/EventManager.h @@ -1,6 +1,6 @@ #include <string> #include <cstdio> -#include <cstdlib> +#include <cstdlib> #include <iostream> #include <fstream> #include <vector> @@ -17,33 +17,33 @@ extern OutputHandler* Log; class EventManager { - private: - std::vector<double> _event_times; - std::vector<std::string> _event_types; - std::vector<std::string> _event_states; - std::vector<int> _event_ids; - std::string _projectFilename; - std::string _projectRootDir; - Building *_building; - double _deltaT; - FILE *_file; - bool _dynamic; - int _eventCounter; +private: + std::vector<double> _event_times; + std::vector<std::string> _event_types; + std::vector<std::string> _event_states; + std::vector<int> _event_ids; + std::string _projectFilename; + std::string _projectRootDir; + Building *_building; + double _deltaT; + FILE *_file; + bool _dynamic; + int _eventCounter; - public: - //Konstruktor - EventManager(Building *_b); - //Dateien einlesen - void SetProjectFilename(const std::string &filename) ; - void SetProjectRootDir(const std::string &filename); - void readEventsXml(); - void listEvents(); - void readEventsTxt(double time); - //Update - void Update_Events(double time, double d); - //Eventhandling - void closeDoor(int id); - void openDoor(int id); - void changeRouting(int id, std::string state); - void getTheEvent(char* c); +public: + //Konstruktor + EventManager(Building *_b); + //Dateien einlesen + void SetProjectFilename(const std::string &filename) ; + void SetProjectRootDir(const std::string &filename); + void readEventsXml(); + void listEvents(); + void readEventsTxt(double time); + //Update + void Update_Events(double time, double d); + //Eventhandling + void closeDoor(int id); + void openDoor(int id); + void changeRouting(int id, std::string state); + void getTheEvent(char* c); }; diff --git a/general/ArgumentParser.cpp b/general/ArgumentParser.cpp index 7f97e16c7c087f25a75df491c3279c4d24e47e37..7d92ebe9a279efbe511c13b41641832e4a2c7a92 100644 --- a/general/ArgumentParser.cpp +++ b/general/ArgumentParser.cpp @@ -23,898 +23,912 @@ using namespace std; -void ArgumentParser::Usage() { - - fprintf(stderr, - "Usage: program options\n\n" - "with the following options (default values in parenthesis):\n\n" - " [-q/--inifile <filepath>] initialisation file( ini.xml found in the actual directory)\n" - " [-n/--number <filepath>] file with the pedestrian distribution in room(./Inputfiles/persons.xml)\n" - " [-t/--tmax <double>] maximal simulation time (500)\n" - " [-d/--dt <double>] time step (0.001)\n" - " [--fps <double>] framerate (1.0 fps)\n" - " [-s/--solver <int>] type of solver, if needed (euler)\n" - " 1: euler\n" - " 2: verlet\n" - " 3: leapfrog\n" - " [-g/--geometry <string>] path to the geometry file (./Inputfiles/geo.xml)\n" - " [-e/--exitstrategy <int>] strategy how the direction to the exit is computed (3).\n" - " 1: Middlepoint of the exit line\n" - " 2: Shortest distance point of the exit line\n" - " 3: Shortest distance point of the exit line, but exit is 20 cm shorter\n" - " [-l/--linkedcells [<double>]] use of linked-cells with optional cell size (default cellsize = 2.2m)\n" - " [-R/--routing <int> [<string>]] routing strategy (1):\n" - " 1: local shortest path\n" - " 2: global shortest path\n" - " 3: quickest path\n" - " [-v/--v0mu <double>] mu for normal distribution of v0, desired velocity (1.24)\n" - " [-V/--v0sigma <double>] sigma for normal distribution of v0, desired velocity (0.26)\n" - " [-a/--ataumu <double>] mu for normal distribution of a_tau, factor for velocity 1st axis (0.53)\n" - " [-A/--atausigma <double>] sigma for normal distribution of a_tau, factor for velocity 1st axis (0.001)\n" - " [-z/--aminmu <double>] mu for normal distribution of a_min, minimal size 1st axis (0.18)\n" - " [-Z/--aminsigma <double>] sigma for normal distribution of a_min, minimal size 1st axis (0.001)\n" - " [-b/--bmaxmu <double>] mu for normal distribution of b_max, maximal size 2nd axis (0.25)\n" - " [-B/--bmaxsigma <double>] sigma for normal distribution of b_max, maximal size 2nd axis (0.001)\n" - " [-y/--bminmu <double>] mu for normal distribution of b_min, minimal size 2nd axis (0.2)\n" - " [-Y/--bminsigma <double>] sigma for normal distribution of b_min, minimal size 2nd axis (0.001)\n" - " [-c/--taumu <double>] mu for normal distribution of tau, reaction time (0.5)\n" - " [-C/--tausigma <double>] sigma for normal distribution of tau, reaction time (0.001)\n" - " [-x/--nuped <double>] strength of forces between pedestrians, factor (0.3)\n" - " [-X/--nuwall <double>] strength of wall forces, factor (0.2)\n" - " [-i/--intpwidthped <double>] interpolation width of pedestrian forces (0.1)\n" - " [-I/--intpwidthwall <double>] interpolation width of wall forces (0.1)\n" - " [-m/--maxfped <double>] interpolation parameter of pedestrian forces (3)\n" - " [-M/--maxfwall <double>] interpolation parameter of wall forces (3)\n" - " [-f/--disteffmaxped <double>] maximal effective distance to pedestrians (2)\n" - " [-F/--disteffmaxwall <double>] maximal effective distance to walls (2)\n" - " [--pathway <filepath>] file for saving pedestrians path\n" - " [-L/--log <int>] log output (0):\n" - " 0: no output\n" - " 1: log output to stdout\n" - " 2: log output to file ./outputfiles/log.txt\n" - " [-T/--output-file <string>] file to write the trajectories ( no trajectories are written if omited0):\n" - " [-P/--streaming-port <int>] stream the ouput to the specified address/port\n" - " [-O/--streaming-ip <string>] stream the ouput to the specified address/port\n" - " [-N/--generate-mesh <string>] write the navigation mesh to the given file\n" - " [-h/--help] this manual output\n" - "\n"); - exit(EXIT_SUCCESS); -} - -ArgumentParser::ArgumentParser() { - // Default parameter values - //pNumberFilename = "inputfiles/persons.xml"; - pSolver = 1; - _projectFile=""; - pTmax = 500; - pfps=1.0; - pdt = 0.01; - pExitStrategy = 2; - pLinkedCells = false; - pLinkedCellSize=2.2; - pV0Mu = 1.24; - pV0Sigma = 0.26; - pBmaxMu = 0.25; - pBmaxSigma = 0.001; - pBminMu = 0.2; - pBminSigma = 0.001; - pAtauMu = 0.53; - pAtauSigma = 0.001; - pAminMu = 0.18; - pAminSigma = 0.001; - pNuPed = 0.4; - pNuWall = 0.2; - pIntPWidthPed = 0.1; - pIntPWidthWall = 0.1; - pMaxFPed = 3; - pMaxFWall = 3; - pDistEffMaxPed = 2; //0.8 - pDistEffMaxWall = 2; - pTauMu = 0.5; - pTauSigma = 0.001; - pLog = 0; - pErrorLogFile="./Logfile.dat"; - //pPathwayFilename=""; - //pRoutingFilename=""; - //pTrafficFilename=""; - pNavMeshFilename=""; - pSeed=0; - pFormat=FORMAT_XML_PLAIN; - pPort=-1; - pHostname="localhost"; - _embedMesh=0; - pMaxOpenMPThreads = omp_get_thread_num(); -} - - - -void ArgumentParser::ParseArgs(int argc, char **argv) { - int c; - int option_index = 0; - - //special case of the default configuration ini.xml - if(argc==1){ - Log->Write("INFO: \tTrying to load the default configuration from the file <ini.xml>"); - ParseIniFile("ini.xml"); - return; - } - - static struct option long_options[] = { - {"number", 1, 0, 'n'}, - {"tmax", 1, 0, 't'}, - {"dt", 1, 0, 'd'}, - {"fps", 1, 0, 'D'}, - {"solver", 1, 0, 's'}, - {"geometry", 1, 0, 'g'}, - {"exitstrategy", 1, 0, 'e'}, - {"randomize", 1, 0, 'r'}, - {"routing", 1, 0, 'R'}, - {"linkedcells", optional_argument, 0, 'l'}, - {"maxompthreads", 1, 0, 'p'}, - {"v0mu", 1, 0, 'v'}, - {"v0sigma", 1, 0, 'V'}, - {"ataumu", 1, 0, 'a'}, - {"atausigma", 1, 0, 'A'}, - {"aminmu", 1, 0, 'z'}, - {"aminsigma", 1, 0, 'Z'}, - {"bmaxmu", 1, 0, 'b'}, - {"bmaxsigma", 1, 0, 'B'}, - {"bminmu", 1, 0, 'y'}, - {"bminsigma", 1, 0, 'Y'}, - {"nuped", 1, 0, 'x'}, - {"nuwall", 1, 0, 'X'}, - {"intpwidthped", 1, 0, 'i'}, - {"intpwidthwall", 1, 0, 'I'}, - {"maxfped", 1, 0, 'm'}, - {"maxfwall", 1, 0, 'M'}, - {"disteffmaxped", 1, 0, 'f'}, - {"disteffmaxwall", 1, 0, 'F'}, - {"taumu", 1, 0, 'c'}, - {"tausigma", 1, 0, 'C'}, - {"log", 1, 0, 'L'}, - {"pathway", 1, 0, 'Q'}, - {"output-file", 1, 0, 'T'}, - {"streaming-port", 1, 0, 'P'}, - {"streaming-ip", 1, 0, 'O'}, - {"help", 0, 0, 'h'}, - {"inifile", optional_argument, 0, 'q'}, - {"generate-mesh", required_argument, 0, 'N'}, - {0, 0, 0, 0} - }; - - while ((c = getopt_long_only(argc, argv, - "n:t:d:s:g:e:r:R:l:p:v:V:a:A:z:Z:b:B:y:Y:x:X:i:I:m:M:f:F:c:C:L:T:O:h:q:D:Q:N:", - long_options, &option_index)) != -1) { - - switch (c) { - case 'T': - { - if (optarg) - pTrajectoriesFile=optarg; - break; - } - case 'P': - { - if (optarg) - pPort=atoi(optarg); - break; - } - case 'O': - { - if (optarg) - pHostname=optarg; - break; - } - case 'L': - { - pLog = atoi(optarg); - break; - } - case 'c': - { - pTauMu = atof(optarg); - break; - } - case 'C': - { - pTauSigma = atof(optarg); - break; - } - case 'f': - { - pDistEffMaxPed = atof(optarg); - break; - } - case 'F': - { - pDistEffMaxWall = atof(optarg); - break; - } - case 'm': - { - pMaxFPed = atof(optarg); - break; - } - case 'M': - { - pMaxFWall = atof(optarg); - break; - } - case 'i': - { - pIntPWidthPed = atof(optarg); - break; - } - case 'I': - { - pIntPWidthWall = atof(optarg); - break; - } - case 'x': - { - pNuPed = atof(optarg); - break; - } - case 'X': - { - pNuWall = atof(optarg); - break; - } - case 'z': - { - pAminMu = atof(optarg); - break; - } - case 'Z': - { - pAminSigma = atof(optarg); - break; - } - case 'a': - { - pAtauMu = atof(optarg); - break; - } - case 'A': - { - pAtauSigma = atof(optarg); - break; - } - case 'y': - { - pBminMu = atof(optarg); - break; - } - case 'Y': - { - pBminSigma = atof(optarg); - break; - } - case 'b': - { - pBmaxMu = atof(optarg); - break; - } - case 'B': - { - pBmaxSigma = atof(optarg); - break; - } - case 'v': - { - pV0Mu = atof(optarg); - break; - } - case 'V': - { - pV0Sigma = atof(optarg); - break; - } - case 'D': - { - pfps=atof(optarg); - break; - } - case 't': - { - double t = atof(optarg); - if (t > 0) - pTmax = t; - else { - Log->Write("ERROR: \tin ArgumentParser::ParseArgs() " - "tmax has to be positiv!!!\n"); - exit(0); - } - break; - } - case 'd': - { - double d = atof(optarg); - if (d > 0) - pdt = d; - else { - Log->Write("ERROR: \tin ArgumentParser::ParseArgs() " - "dt has to be positiv!!!\n"); - exit(0); - } - break; - } - case 's': - { - int s = atoi(optarg); - if (s == 1 || s==2 || s==3) // spaeter erweitern - pSolver = s; - else { - Log->Write("ERROR: \tin ArgumentParser::ParseArgs() " - "wrong value for solver type!!!\n"); - exit(0); - } - break; - } - case 'e': - { - int e = atoi(optarg); - if (e == 1 || e == 2 || e == 3 || e == 4 ) - pExitStrategy = e; - else { - Log->Write("ERROR: \tin ArgumentParser::ParseArgs() " - "wrong value for exit strategy!!!\n"); - exit(0); - } - break; - } - case 'R': // TODO: are these options still correct ? - { - printf("---%s\n",optarg); - int r = atoi(optarg); - switch(r){ - case 1: - pRoutingStrategies.push_back(make_pair (1,ROUTING_LOCAL_SHORTEST)); - break; - case 2: - pRoutingStrategies.push_back(make_pair (2, ROUTING_GLOBAL_SHORTEST)); - break; - case 3: - pRoutingStrategies.push_back(make_pair (3,ROUTING_QUICKEST)); - break; - case 4: - pRoutingStrategies.push_back(make_pair (4,ROUTING_DYNAMIC)); - break; - case 5: - pRoutingStrategies.push_back(make_pair (5,ROUTING_NAV_MESH)); - break; - case 6: - pRoutingStrategies.push_back(make_pair (6,ROUTING_DUMMY)); - break; - default: - Log->Write("ERROR: \tin ArgumentParser::ParseArgs() " - "wrong value for routing strategy!!!\n"); - exit(0); - break; - } - break; - } - case 'l': - { - pLinkedCells = true; - if (optarg) - pLinkedCellSize=atof(optarg); - break; - } - break; - - case 'q': - { - string inifile="ini.xml"; - if (optarg) - inifile=optarg; - ParseIniFile(inifile); - return; //stop looking - } - break; - - case 'p': - pMaxOpenMPThreads = atof(optarg); +void ArgumentParser::Usage() +{ + + fprintf(stderr, + "Usage: program options\n\n" + "with the following options (default values in parenthesis):\n\n" + " [-q/--inifile <filepath>] initialisation file( ini.xml found in the actual directory)\n" + " [-n/--number <filepath>] file with the pedestrian distribution in room(./Inputfiles/persons.xml)\n" + " [-t/--tmax <double>] maximal simulation time (500)\n" + " [-d/--dt <double>] time step (0.001)\n" + " [--fps <double>] framerate (1.0 fps)\n" + " [-s/--solver <int>] type of solver, if needed (euler)\n" + " 1: euler\n" + " 2: verlet\n" + " 3: leapfrog\n" + " [-g/--geometry <string>] path to the geometry file (./Inputfiles/geo.xml)\n" + " [-e/--exitstrategy <int>] strategy how the direction to the exit is computed (3).\n" + " 1: Middlepoint of the exit line\n" + " 2: Shortest distance point of the exit line\n" + " 3: Shortest distance point of the exit line, but exit is 20 cm shorter\n" + " [-l/--linkedcells [<double>]] use of linked-cells with optional cell size (default cellsize = 2.2m)\n" + " [-R/--routing <int> [<string>]] routing strategy (1):\n" + " 1: local shortest path\n" + " 2: global shortest path\n" + " 3: quickest path\n" + " [-v/--v0mu <double>] mu for normal distribution of v0, desired velocity (1.24)\n" + " [-V/--v0sigma <double>] sigma for normal distribution of v0, desired velocity (0.26)\n" + " [-a/--ataumu <double>] mu for normal distribution of a_tau, factor for velocity 1st axis (0.53)\n" + " [-A/--atausigma <double>] sigma for normal distribution of a_tau, factor for velocity 1st axis (0.001)\n" + " [-z/--aminmu <double>] mu for normal distribution of a_min, minimal size 1st axis (0.18)\n" + " [-Z/--aminsigma <double>] sigma for normal distribution of a_min, minimal size 1st axis (0.001)\n" + " [-b/--bmaxmu <double>] mu for normal distribution of b_max, maximal size 2nd axis (0.25)\n" + " [-B/--bmaxsigma <double>] sigma for normal distribution of b_max, maximal size 2nd axis (0.001)\n" + " [-y/--bminmu <double>] mu for normal distribution of b_min, minimal size 2nd axis (0.2)\n" + " [-Y/--bminsigma <double>] sigma for normal distribution of b_min, minimal size 2nd axis (0.001)\n" + " [-c/--taumu <double>] mu for normal distribution of tau, reaction time (0.5)\n" + " [-C/--tausigma <double>] sigma for normal distribution of tau, reaction time (0.001)\n" + " [-x/--nuped <double>] strength of forces between pedestrians, factor (0.3)\n" + " [-X/--nuwall <double>] strength of wall forces, factor (0.2)\n" + " [-i/--intpwidthped <double>] interpolation width of pedestrian forces (0.1)\n" + " [-I/--intpwidthwall <double>] interpolation width of wall forces (0.1)\n" + " [-m/--maxfped <double>] interpolation parameter of pedestrian forces (3)\n" + " [-M/--maxfwall <double>] interpolation parameter of wall forces (3)\n" + " [-f/--disteffmaxped <double>] maximal effective distance to pedestrians (2)\n" + " [-F/--disteffmaxwall <double>] maximal effective distance to walls (2)\n" + " [--pathway <filepath>] file for saving pedestrians path\n" + " [-L/--log <int>] log output (0):\n" + " 0: no output\n" + " 1: log output to stdout\n" + " 2: log output to file ./outputfiles/log.txt\n" + " [-T/--output-file <string>] file to write the trajectories ( no trajectories are written if omited0):\n" + " [-P/--streaming-port <int>] stream the ouput to the specified address/port\n" + " [-O/--streaming-ip <string>] stream the ouput to the specified address/port\n" + " [-N/--generate-mesh <string>] write the navigation mesh to the given file\n" + " [-h/--help] this manual output\n" + "\n"); + exit(EXIT_SUCCESS); +} + +ArgumentParser::ArgumentParser() +{ + // Default parameter values + //pNumberFilename = "inputfiles/persons.xml"; + pSolver = 1; + _projectFile=""; + pTmax = 500; + pfps=1.0; + pdt = 0.01; + pExitStrategy = 2; + pLinkedCells = false; + pLinkedCellSize=2.2; + pV0Mu = 1.24; + pV0Sigma = 0.26; + pBmaxMu = 0.25; + pBmaxSigma = 0.001; + pBminMu = 0.2; + pBminSigma = 0.001; + pAtauMu = 0.53; + pAtauSigma = 0.001; + pAminMu = 0.18; + pAminSigma = 0.001; + pNuPed = 0.4; + pNuWall = 0.2; + pIntPWidthPed = 0.1; + pIntPWidthWall = 0.1; + pMaxFPed = 3; + pMaxFWall = 3; + pDistEffMaxPed = 2; //0.8 + pDistEffMaxWall = 2; + pTauMu = 0.5; + pTauSigma = 0.001; + pLog = 0; + pErrorLogFile="./Logfile.dat"; + //pPathwayFilename=""; + //pRoutingFilename=""; + //pTrafficFilename=""; + pNavMeshFilename=""; + pSeed=0; + pFormat=FORMAT_XML_PLAIN; + pPort=-1; + pHostname="localhost"; + _embedMesh=0; + pMaxOpenMPThreads = omp_get_thread_num(); +} + + + +void ArgumentParser::ParseArgs(int argc, char **argv) +{ + int c; + int option_index = 0; + + //special case of the default configuration ini.xml + if(argc==1) { + Log->Write("INFO: \tTrying to load the default configuration from the file <ini.xml>"); + ParseIniFile("ini.xml"); + return; + } + + static struct option long_options[] = { + {"number", 1, 0, 'n'}, + {"tmax", 1, 0, 't'}, + {"dt", 1, 0, 'd'}, + {"fps", 1, 0, 'D'}, + {"solver", 1, 0, 's'}, + {"geometry", 1, 0, 'g'}, + {"exitstrategy", 1, 0, 'e'}, + {"randomize", 1, 0, 'r'}, + {"routing", 1, 0, 'R'}, + {"linkedcells", optional_argument, 0, 'l'}, + {"maxompthreads", 1, 0, 'p'}, + {"v0mu", 1, 0, 'v'}, + {"v0sigma", 1, 0, 'V'}, + {"ataumu", 1, 0, 'a'}, + {"atausigma", 1, 0, 'A'}, + {"aminmu", 1, 0, 'z'}, + {"aminsigma", 1, 0, 'Z'}, + {"bmaxmu", 1, 0, 'b'}, + {"bmaxsigma", 1, 0, 'B'}, + {"bminmu", 1, 0, 'y'}, + {"bminsigma", 1, 0, 'Y'}, + {"nuped", 1, 0, 'x'}, + {"nuwall", 1, 0, 'X'}, + {"intpwidthped", 1, 0, 'i'}, + {"intpwidthwall", 1, 0, 'I'}, + {"maxfped", 1, 0, 'm'}, + {"maxfwall", 1, 0, 'M'}, + {"disteffmaxped", 1, 0, 'f'}, + {"disteffmaxwall", 1, 0, 'F'}, + {"taumu", 1, 0, 'c'}, + {"tausigma", 1, 0, 'C'}, + {"log", 1, 0, 'L'}, + {"pathway", 1, 0, 'Q'}, + {"output-file", 1, 0, 'T'}, + {"streaming-port", 1, 0, 'P'}, + {"streaming-ip", 1, 0, 'O'}, + {"help", 0, 0, 'h'}, + {"inifile", optional_argument, 0, 'q'}, + {"generate-mesh", required_argument, 0, 'N'}, + {0, 0, 0, 0} + }; + + while ((c = getopt_long_only(argc, argv, + "n:t:d:s:g:e:r:R:l:p:v:V:a:A:z:Z:b:B:y:Y:x:X:i:I:m:M:f:F:c:C:L:T:O:h:q:D:Q:N:", + long_options, &option_index)) != -1) { + + switch (c) { + case 'T': { + if (optarg) + pTrajectoriesFile=optarg; + break; + } + case 'P': { + if (optarg) + pPort=atoi(optarg); + break; + } + case 'O': { + if (optarg) + pHostname=optarg; + break; + } + case 'L': { + pLog = atoi(optarg); + break; + } + case 'c': { + pTauMu = atof(optarg); + break; + } + case 'C': { + pTauSigma = atof(optarg); + break; + } + case 'f': { + pDistEffMaxPed = atof(optarg); + break; + } + case 'F': { + pDistEffMaxWall = atof(optarg); + break; + } + case 'm': { + pMaxFPed = atof(optarg); + break; + } + case 'M': { + pMaxFWall = atof(optarg); + break; + } + case 'i': { + pIntPWidthPed = atof(optarg); + break; + } + case 'I': { + pIntPWidthWall = atof(optarg); + break; + } + case 'x': { + pNuPed = atof(optarg); + break; + } + case 'X': { + pNuWall = atof(optarg); + break; + } + case 'z': { + pAminMu = atof(optarg); + break; + } + case 'Z': { + pAminSigma = atof(optarg); + break; + } + case 'a': { + pAtauMu = atof(optarg); + break; + } + case 'A': { + pAtauSigma = atof(optarg); + break; + } + case 'y': { + pBminMu = atof(optarg); + break; + } + case 'Y': { + pBminSigma = atof(optarg); + break; + } + case 'b': { + pBmaxMu = atof(optarg); + break; + } + case 'B': { + pBmaxSigma = atof(optarg); + break; + } + case 'v': { + pV0Mu = atof(optarg); + break; + } + case 'V': { + pV0Sigma = atof(optarg); + break; + } + case 'D': { + pfps=atof(optarg); + break; + } + case 't': { + double t = atof(optarg); + if (t > 0) + pTmax = t; + else { + Log->Write("ERROR: \tin ArgumentParser::ParseArgs() " + "tmax has to be positiv!!!\n"); + exit(0); + } + break; + } + case 'd': { + double d = atof(optarg); + if (d > 0) + pdt = d; + else { + Log->Write("ERROR: \tin ArgumentParser::ParseArgs() " + "dt has to be positiv!!!\n"); + exit(0); + } + break; + } + case 's': { + int s = atoi(optarg); + if (s == 1 || s==2 || s==3) // spaeter erweitern + pSolver = s; + else { + Log->Write("ERROR: \tin ArgumentParser::ParseArgs() " + "wrong value for solver type!!!\n"); + exit(0); + } + break; + } + case 'e': { + int e = atoi(optarg); + if (e == 1 || e == 2 || e == 3 || e == 4 ) + pExitStrategy = e; + else { + Log->Write("ERROR: \tin ArgumentParser::ParseArgs() " + "wrong value for exit strategy!!!\n"); + exit(0); + } + break; + } + case 'R': { // TODO: are these options still correct ? + printf("---%s\n",optarg); + int r = atoi(optarg); + switch(r) { + case 1: + pRoutingStrategies.push_back(make_pair (1,ROUTING_LOCAL_SHORTEST)); + break; + case 2: + pRoutingStrategies.push_back(make_pair (2, ROUTING_GLOBAL_SHORTEST)); + break; + case 3: + pRoutingStrategies.push_back(make_pair (3,ROUTING_QUICKEST)); + break; + case 4: + pRoutingStrategies.push_back(make_pair (4,ROUTING_DYNAMIC)); + break; + case 5: + pRoutingStrategies.push_back(make_pair (5,ROUTING_NAV_MESH)); + break; + case 6: + pRoutingStrategies.push_back(make_pair (6,ROUTING_DUMMY)); + break; + default: + Log->Write("ERROR: \tin ArgumentParser::ParseArgs() " + "wrong value for routing strategy!!!\n"); + exit(0); + break; + } + break; + } + case 'l': { + pLinkedCells = true; + if (optarg) + pLinkedCellSize=atof(optarg); + break; + } + break; + + case 'q': { + string inifile="ini.xml"; + if (optarg) + inifile=optarg; + ParseIniFile(inifile); + return; //stop looking + } + break; + + case 'p': + pMaxOpenMPThreads = atof(optarg); #ifdef _OPENMP - omp_set_num_threads(pMaxOpenMPThreads); + omp_set_num_threads(pMaxOpenMPThreads); #endif - break; - - case 'h': - Usage(); - break; - - case 'N': - pNavMeshFilename=optarg; - break; - - default: - { - Log->Write("ERROR: \tin ArgumentParser::ParseArgs() " - "wrong program options!!!\n"); - Usage(); - exit(EXIT_FAILURE); - } - } - } - - // other special case where a single configuration file is submitted - if(argc==2){ - ParseIniFile(argv[1]); - return; - } -} - - -void ArgumentParser::ParseIniFile(string inifile){ - - Log->Write("INFO: \tLoading and parsing the project file file <%s>",inifile.c_str()); - _projectFile=inifile; - - //extract and set the project root dir - size_t found=inifile.find_last_of("/\\"); - if (found!=string::npos) - _projectRootDir= inifile.substr(0,found) + "/"; - - //cout<<inifile<<endl; - //cout<<_projectRootDir<<endl; exit(0); - //char *real_path = _realpath(path, NULL); - // use real_path - //free(real_path); - - TiXmlDocument doc(inifile); - if (!doc.LoadFile()){ - Log->Write("ERROR: \t%s", doc.ErrorDesc()); - Log->Write("ERROR: \t could not parse the project file"); - exit(EXIT_FAILURE); - } - - // everything is fine. proceed with parsing - - TiXmlElement* xMainNode = doc.RootElement(); - if( ! xMainNode ) { - Log->Write("ERROR:\tRoot element does not exist"); - exit(EXIT_FAILURE); - } - - if( xMainNode->ValueStr () != "JuPedSim" ) { - Log->Write("ERROR:\tRoot element value is not 'JuPedSim'."); - exit(EXIT_FAILURE); - } - - //check the header version - if(!xMainNode->Attribute("version")){ - Log->Write("ERROR:\t There is no header version. I am assuming %s",JPS_VERSION); - } - else - if(string(xMainNode->Attribute("version"))!=JPS_VERSION){ - Log->Write("ERROR:\t Wrong header version. Only version %s is supported.",JPS_VERSION); - exit(EXIT_FAILURE); - } - - //seed - if(xMainNode->FirstChild("seed")){ - pSeed=atoi(xMainNode->FirstChild("seed")->FirstChild()->Value()); - srand(pSeed); - Log->Write("INFO: \tseed < %d >",pSeed); - } - - // max simulation time - if(xMainNode->FirstChild("max_sim_time")){ - const char* tmax=xMainNode->FirstChildElement("max_sim_time")->FirstChild()->Value(); - //const char* unit=xMainNode->FirstChildElement("max_sim_time")->Attribute("unit"); - pTmax=atof(tmax); - //Log->Write("INFO: \tpTmax <"+string(tmax)+" " +string(unit) +" (unit ignored)>"); - Log->Write("INFO: \tpTmax <"+string(tmax)+" (seconds) >"); - } - - //logfile - if(xMainNode->FirstChild("logfile")){ - pErrorLogFile=_projectRootDir+xMainNode->FirstChild("logfile")->FirstChild()->Value(); - pLog=2; - Log->Write("INFO: \tlogfile <"+(pErrorLogFile)+">"); - } - - //trajectories - TiXmlNode* xTrajectories=xMainNode->FirstChild("trajectories"); - if(xTrajectories){ - - xMainNode->FirstChildElement("trajectories")->Attribute("fps",&pfps); - - string format= xMainNode->FirstChildElement("trajectories")->Attribute("format")? - xMainNode->FirstChildElement("trajectories")->Attribute("format"):"xml-plain"; - if(xMainNode->FirstChildElement("trajectories")->Attribute("embed_mesh")) - _embedMesh = string(xMainNode->FirstChildElement("trajectories")->Attribute("embed_mesh"))=="true"?1:0; - - if(format=="xml-plain") pFormat=FORMAT_XML_PLAIN; - if(format=="xml-plain" && _embedMesh==1) pFormat=FORMAT_XML_PLAIN_WITH_MESH; - if(format=="xml-bin") pFormat=FORMAT_XML_BIN; - if(format=="plain") pFormat=FORMAT_PLAIN; - if(format=="vtk") pFormat=FORMAT_VTK; - - - //a file descriptor was given - if(xTrajectories->FirstChild("file")){ - const char* tmp = xTrajectories->FirstChildElement("file")->Attribute("location"); - if(tmp) pTrajectoriesFile = _projectRootDir+tmp; - Log->Write("INFO: \toutput file <"+string(pTrajectoriesFile)+">"); - Log->Write("INFO: \tin format <%s> at <%f> frames per seconds",format.c_str(),pfps); - } - - if(xTrajectories->FirstChild("socket")){ - const char* tmp = xTrajectories->FirstChildElement("socket")->Attribute("hostname"); - if(tmp) pHostname = tmp; - xTrajectories->FirstChildElement("socket")->Attribute("port",&pPort); - Log->Write("INFO: \tStreaming results to output [%s:%d] ",pHostname.c_str(),pPort); - } - } - - //pick up which model to use - TiXmlElement* xGCFM=xMainNode->FirstChild("operational_models")->FirstChildElement("model"); - string modelName = string(xGCFM->Attribute("description")); - if(modelName == "gcfm" || modelName == "gompertz"){ - - TiXmlNode* xPara=xGCFM->FirstChild("parameters"); - - Log->Write("INFO:\t%s model used\n", modelName.c_str()); - // For convenience. This moved to the header as it is not model specific - if(xPara->FirstChild("tmax")){ - Log->Write("ERROR: \tthe maximal simulation time section moved to the header!!!"); - Log->Write("ERROR: \t\t <max_sim_time> </max_sim_time>\n"); - } - - //solver - if(xPara->FirstChild("solver")){ - string solver=xPara->FirstChild("solver")->FirstChild()->Value(); - if(solver=="euler") pSolver=1; - else if(solver=="verlet") pSolver=2; - else if(solver=="leapfrog") pSolver=3; - else { - Log->Write("ERROR: \twrong value for solver type!!!\n"); - exit(EXIT_FAILURE); - } - Log->Write("INFO: \tpSolver <"+string(solver)+">"); - } - - //stepsize - if(xPara->FirstChild("stepsize")){ - const char* stepsize=xPara->FirstChild("stepsize")->FirstChild()->Value(); - if(stepsize) - pdt=atof(stepsize); - Log->Write("INFO: \tstepsize <%f>",pdt); - } - - //exit crossing strategy - if(xPara->FirstChild("exitCrossingStrategy")){ - const char* tmp=xPara->FirstChild("exitCrossingStrategy")->FirstChild()->Value(); - if(tmp) pExitStrategy= atoi(tmp); - Log->Write("INFO: \texitCrossingStrategy < %d >", pExitStrategy); - } - - //linked-cells - if(xPara->FirstChild("linkedcells")){ - string linkedcells=xPara->FirstChildElement("linkedcells")->Attribute("enabled"); - string cell_size=xPara->FirstChildElement("linkedcells")->Attribute("cell_size"); - - if(linkedcells=="true"){ - pLinkedCells=true; - pLinkedCellSize=atof(cell_size.c_str()); - Log->Write("INFO: \tlinked cells enabled with size <"+cell_size+">"); - }else{ - Log->Write("WARNING: \tinvalid parameters for linkedcells"); - } - } - - //desired speed - if(xPara->FirstChild("v0")){ - string mu=xPara->FirstChildElement("v0")->Attribute("mu"); - string sigma=xPara->FirstChildElement("v0")->Attribute("sigma"); - pV0Mu=atof(mu.c_str()); - pV0Sigma=atof(sigma.c_str()); - Log->Write("INFO: \tdesired velocity mu=" +mu +" ,"+ " sigma="+sigma+" "); - } - - //bmax - if(xPara->FirstChild("bmax")){ - string mu=xPara->FirstChildElement("bmax")->Attribute("mu"); - string sigma=xPara->FirstChildElement("bmax")->Attribute("sigma"); - pBmaxMu=atof(mu.c_str()); - pBmaxSigma=atof(sigma.c_str()); - Log->Write("INFO: \tBmax mu=" +mu +" ,"+ " sigma="+sigma+" "); - } - - //bmin - if(xPara->FirstChild("bmin")){ - string mu=xPara->FirstChildElement("bmin")->Attribute("mu"); - string sigma=xPara->FirstChildElement("bmin")->Attribute("sigma"); - pBminMu=atof(mu.c_str()); - pBminSigma=atof(sigma.c_str()); - Log->Write("INFO: \tBmin mu=" +mu +" ,"+ " sigma="+sigma+" "); - } - - //amin - if(xPara->FirstChild("amin")){ - string mu=xPara->FirstChildElement("amin")->Attribute("mu"); - string sigma=xPara->FirstChildElement("amin")->Attribute("sigma"); - pAminMu=atof(mu.c_str()); - pAminSigma=atof(sigma.c_str()); - Log->Write("INFO: \tAmin mu=" +mu +" ,"+ " sigma="+sigma+" "); - } - //tau - if(xPara->FirstChild("tau")){ - string mu=xPara->FirstChildElement("tau")->Attribute("mu"); - string sigma=xPara->FirstChildElement("tau")->Attribute("sigma"); - pTauMu=atof(mu.c_str()); - pTauSigma=atof(sigma.c_str()); - Log->Write("INFO: \tTau mu=" +mu +" ,"+ " sigma="+sigma+" "); - } - //atau - if(xPara->FirstChild("atau")){ - string mu=xPara->FirstChildElement("atau")->Attribute("mu"); - string sigma=xPara->FirstChildElement("atau")->Attribute("sigma"); - pAtauMu=atof(mu.c_str()); - pAtauSigma=atof(sigma.c_str()); - Log->Write("INFO: \tAtau mu=" +mu +" ,"+ " sigma="+sigma+" "); - } - - //force_ped - if(modelName == "gcfm"){ - pModel = 1; - if(xPara->FirstChild("force_ped")){ - string nu=xPara->FirstChildElement("force_ped")->Attribute("nu"); - string dist_max=xPara->FirstChildElement("force_ped")->Attribute("dist_max"); - string disteff_max=xPara->FirstChildElement("force_ped")->Attribute("disteff_max"); - string interpolation_width=xPara->FirstChildElement("force_ped")->Attribute("interpolation_width"); - - pMaxFPed=atof(dist_max.c_str()); - pNuPed=atof(nu.c_str()); - pDistEffMaxPed=atof(disteff_max.c_str()); - pIntPWidthPed=atof(interpolation_width.c_str()); - Log->Write("INFO: \tfrep_ped mu=" +nu +", dist_max="+dist_max+", disteff_max=" - + disteff_max+ ", interpolation_width="+interpolation_width); - } - - //force_wall - if(xPara->FirstChild("force_wall")){ - string nu=xPara->FirstChildElement("force_wall")->Attribute("nu"); - string dist_max=xPara->FirstChildElement("force_wall")->Attribute("dist_max"); - string disteff_max=xPara->FirstChildElement("force_wall")->Attribute("disteff_max"); - string interpolation_width=xPara->FirstChildElement("force_wall")->Attribute("interpolation_width"); - pMaxFWall=atof(dist_max.c_str()); - pNuWall=atof(nu.c_str()); - pDistEffMaxWall=atof(disteff_max.c_str()); - pIntPWidthWall=atof(interpolation_width.c_str()); - Log->Write("INFO: \tfrep_wall mu=" +nu +", dist_max="+dist_max+", disteff_max=" - + disteff_max+ ", interpolation_width="+interpolation_width); - } - }//if gcfm - else if(modelName == "gompertz"){ - pModel = 2; - //force_ped - if(xPara->FirstChild("force_ped")){ - string nu=xPara->FirstChildElement("force_ped")->Attribute("nu"); - pNuPed=atof(nu.c_str()); - Log->Write("INFO: \tfrep_ped mu=" +nu); - - } - //force_wall - if(xPara->FirstChild("force_wall")){ - string nu=xPara->FirstChildElement("force_wall")->Attribute("nu"); - pNuWall=atof(nu.c_str()); - Log->Write("INFO: \tfrep_wall mu=" +nu); - } - } - }//gcfm - else - { - Log->Write("INFO: \tno gcfm parameter values found"); - } - - - //route choice strategy - TiXmlNode* xRouters=xMainNode->FirstChild("route_choice_models"); - - if(!xRouters) { - Log->Write("ERROR:\tNo routers found."); - exit(EXIT_FAILURE); - } - - for(TiXmlElement* e = xRouters->FirstChildElement("router"); e; - e = e->NextSiblingElement("router")) { - - string strategy=e->Attribute("description"); - int id=atoi(e->Attribute("router_id")); - - if(strategy=="local_shortest") - pRoutingStrategies.push_back(make_pair(id,ROUTING_LOCAL_SHORTEST)); - else if(strategy=="global_shortest") - pRoutingStrategies.push_back(make_pair(id,ROUTING_GLOBAL_SHORTEST)); - else if(strategy=="quickest") - pRoutingStrategies.push_back(make_pair(id,ROUTING_QUICKEST)); - else if(strategy=="dynamic") - pRoutingStrategies.push_back(make_pair(id,ROUTING_DYNAMIC)); - else if(strategy=="nav_mesh") - pRoutingStrategies.push_back(make_pair(id,ROUTING_NAV_MESH)); - else if(strategy=="dummy") - pRoutingStrategies.push_back(make_pair(id,ROUTING_DUMMY)); - else if(strategy=="global_safest") - pRoutingStrategies.push_back(make_pair(id,ROUTING_SAFEST)); - else if(strategy=="cognitive_map") - pRoutingStrategies.push_back(make_pair(id,ROUTING_COGNITIVEMAP)); - else{ - Log->Write("ERROR: \twrong value for routing strategy [%s]!!!\n",strategy.c_str()); - exit(EXIT_FAILURE); - } - } - - Log->Write("INFO: \tParsing the project file completed"); -} - - -int ArgumentParser::GetModel() const { return pModel; } -const FileFormat& ArgumentParser::GetFileFormat() const { - return pFormat; -} -const string& ArgumentParser::GetHostname() const { - return pHostname; -} -void ArgumentParser::SetHostname(const string& hostname) { - pHostname = hostname; -} -int ArgumentParser::GetPort() const { - return pPort; -} -void ArgumentParser::SetPort(int port) { - pPort = port; -} -int ArgumentParser::GetSolver() const { - return pSolver; -} - -double ArgumentParser::GetTmax() const { - return pTmax; -} - -double ArgumentParser::Getdt() const { - return pdt; -} - -double ArgumentParser::Getfps() const { - return pfps; + break; + + case 'h': + Usage(); + break; + + case 'N': + pNavMeshFilename=optarg; + break; + + default: { + Log->Write("ERROR: \tin ArgumentParser::ParseArgs() " + "wrong program options!!!\n"); + Usage(); + exit(EXIT_FAILURE); + } + } + } + + // other special case where a single configuration file is submitted + if(argc==2) { + ParseIniFile(argv[1]); + return; + } +} + + +void ArgumentParser::ParseIniFile(string inifile) +{ + + Log->Write("INFO: \tLoading and parsing the project file file <%s>",inifile.c_str()); + _projectFile=inifile; + + //extract and set the project root dir + size_t found=inifile.find_last_of("/\\"); + if (found!=string::npos) + _projectRootDir= inifile.substr(0,found) + "/"; + + //cout<<inifile<<endl; + //cout<<_projectRootDir<<endl; exit(0); + //char *real_path = _realpath(path, NULL); + // use real_path + //free(real_path); + + TiXmlDocument doc(inifile); + if (!doc.LoadFile()) { + Log->Write("ERROR: \t%s", doc.ErrorDesc()); + Log->Write("ERROR: \t could not parse the project file"); + exit(EXIT_FAILURE); + } + + // everything is fine. proceed with parsing + + TiXmlElement* xMainNode = doc.RootElement(); + if( ! xMainNode ) { + Log->Write("ERROR:\tRoot element does not exist"); + exit(EXIT_FAILURE); + } + + if( xMainNode->ValueStr () != "JuPedSim" ) { + Log->Write("ERROR:\tRoot element value is not 'JuPedSim'."); + exit(EXIT_FAILURE); + } + + //check the header version + if(!xMainNode->Attribute("version")) { + Log->Write("ERROR:\t There is no header version. I am assuming %s",JPS_VERSION); + } else if(string(xMainNode->Attribute("version"))!=JPS_VERSION) { + Log->Write("ERROR:\t Wrong header version. Only version %s is supported.",JPS_VERSION); + exit(EXIT_FAILURE); + } + + //seed + if(xMainNode->FirstChild("seed")) { + pSeed=atoi(xMainNode->FirstChild("seed")->FirstChild()->Value()); + srand(pSeed); + Log->Write("INFO: \tseed < %d >",pSeed); + } + + // max simulation time + if(xMainNode->FirstChild("max_sim_time")) { + const char* tmax=xMainNode->FirstChildElement("max_sim_time")->FirstChild()->Value(); + //const char* unit=xMainNode->FirstChildElement("max_sim_time")->Attribute("unit"); + pTmax=atof(tmax); + //Log->Write("INFO: \tpTmax <"+string(tmax)+" " +string(unit) +" (unit ignored)>"); + Log->Write("INFO: \tpTmax <"+string(tmax)+" (seconds) >"); + } + + //logfile + if(xMainNode->FirstChild("logfile")) { + pErrorLogFile=_projectRootDir+xMainNode->FirstChild("logfile")->FirstChild()->Value(); + pLog=2; + Log->Write("INFO: \tlogfile <"+(pErrorLogFile)+">"); + } + + //trajectories + TiXmlNode* xTrajectories=xMainNode->FirstChild("trajectories"); + if(xTrajectories) { + + xMainNode->FirstChildElement("trajectories")->Attribute("fps",&pfps); + + string format= xMainNode->FirstChildElement("trajectories")->Attribute("format")? + xMainNode->FirstChildElement("trajectories")->Attribute("format"):"xml-plain"; + if(xMainNode->FirstChildElement("trajectories")->Attribute("embed_mesh")) + _embedMesh = string(xMainNode->FirstChildElement("trajectories")->Attribute("embed_mesh"))=="true"?1:0; + + if(format=="xml-plain") pFormat=FORMAT_XML_PLAIN; + if(format=="xml-plain" && _embedMesh==1) pFormat=FORMAT_XML_PLAIN_WITH_MESH; + if(format=="xml-bin") pFormat=FORMAT_XML_BIN; + if(format=="plain") pFormat=FORMAT_PLAIN; + if(format=="vtk") pFormat=FORMAT_VTK; + + + //a file descriptor was given + if(xTrajectories->FirstChild("file")) { + const char* tmp = xTrajectories->FirstChildElement("file")->Attribute("location"); + if(tmp) pTrajectoriesFile = _projectRootDir+tmp; + Log->Write("INFO: \toutput file <"+string(pTrajectoriesFile)+">"); + Log->Write("INFO: \tin format <%s> at <%f> frames per seconds",format.c_str(),pfps); + } + + if(xTrajectories->FirstChild("socket")) { + const char* tmp = xTrajectories->FirstChildElement("socket")->Attribute("hostname"); + if(tmp) pHostname = tmp; + xTrajectories->FirstChildElement("socket")->Attribute("port",&pPort); + Log->Write("INFO: \tStreaming results to output [%s:%d] ",pHostname.c_str(),pPort); + } + } + + //pick up which model to use + TiXmlElement* xGCFM=xMainNode->FirstChild("operational_models")->FirstChildElement("model"); + string modelName = string(xGCFM->Attribute("description")); + if(modelName == "gcfm" || modelName == "gompertz") { + + TiXmlNode* xPara=xGCFM->FirstChild("parameters"); + + Log->Write("INFO:\t%s model used\n", modelName.c_str()); + // For convenience. This moved to the header as it is not model specific + if(xPara->FirstChild("tmax")) { + Log->Write("ERROR: \tthe maximal simulation time section moved to the header!!!"); + Log->Write("ERROR: \t\t <max_sim_time> </max_sim_time>\n"); + } + + //solver + if(xPara->FirstChild("solver")) { + string solver=xPara->FirstChild("solver")->FirstChild()->Value(); + if(solver=="euler") pSolver=1; + else if(solver=="verlet") pSolver=2; + else if(solver=="leapfrog") pSolver=3; + else { + Log->Write("ERROR: \twrong value for solver type!!!\n"); + exit(EXIT_FAILURE); + } + Log->Write("INFO: \tpSolver <"+string(solver)+">"); + } + + //stepsize + if(xPara->FirstChild("stepsize")) { + const char* stepsize=xPara->FirstChild("stepsize")->FirstChild()->Value(); + if(stepsize) + pdt=atof(stepsize); + Log->Write("INFO: \tstepsize <%f>",pdt); + } + + //exit crossing strategy + if(xPara->FirstChild("exitCrossingStrategy")) { + const char* tmp=xPara->FirstChild("exitCrossingStrategy")->FirstChild()->Value(); + if(tmp) pExitStrategy= atoi(tmp); + Log->Write("INFO: \texitCrossingStrategy < %d >", pExitStrategy); + } + + //linked-cells + if(xPara->FirstChild("linkedcells")) { + string linkedcells=xPara->FirstChildElement("linkedcells")->Attribute("enabled"); + string cell_size=xPara->FirstChildElement("linkedcells")->Attribute("cell_size"); + + if(linkedcells=="true") { + pLinkedCells=true; + pLinkedCellSize=atof(cell_size.c_str()); + Log->Write("INFO: \tlinked cells enabled with size <"+cell_size+">"); + } else { + Log->Write("WARNING: \tinvalid parameters for linkedcells"); + } + } + + //desired speed + if(xPara->FirstChild("v0")) { + string mu=xPara->FirstChildElement("v0")->Attribute("mu"); + string sigma=xPara->FirstChildElement("v0")->Attribute("sigma"); + pV0Mu=atof(mu.c_str()); + pV0Sigma=atof(sigma.c_str()); + Log->Write("INFO: \tdesired velocity mu=" +mu +" ,"+ " sigma="+sigma+" "); + } + + //bmax + if(xPara->FirstChild("bmax")) { + string mu=xPara->FirstChildElement("bmax")->Attribute("mu"); + string sigma=xPara->FirstChildElement("bmax")->Attribute("sigma"); + pBmaxMu=atof(mu.c_str()); + pBmaxSigma=atof(sigma.c_str()); + Log->Write("INFO: \tBmax mu=" +mu +" ,"+ " sigma="+sigma+" "); + } + + //bmin + if(xPara->FirstChild("bmin")) { + string mu=xPara->FirstChildElement("bmin")->Attribute("mu"); + string sigma=xPara->FirstChildElement("bmin")->Attribute("sigma"); + pBminMu=atof(mu.c_str()); + pBminSigma=atof(sigma.c_str()); + Log->Write("INFO: \tBmin mu=" +mu +" ,"+ " sigma="+sigma+" "); + } + + //amin + if(xPara->FirstChild("amin")) { + string mu=xPara->FirstChildElement("amin")->Attribute("mu"); + string sigma=xPara->FirstChildElement("amin")->Attribute("sigma"); + pAminMu=atof(mu.c_str()); + pAminSigma=atof(sigma.c_str()); + Log->Write("INFO: \tAmin mu=" +mu +" ,"+ " sigma="+sigma+" "); + } + //tau + if(xPara->FirstChild("tau")) { + string mu=xPara->FirstChildElement("tau")->Attribute("mu"); + string sigma=xPara->FirstChildElement("tau")->Attribute("sigma"); + pTauMu=atof(mu.c_str()); + pTauSigma=atof(sigma.c_str()); + Log->Write("INFO: \tTau mu=" +mu +" ,"+ " sigma="+sigma+" "); + } + //atau + if(xPara->FirstChild("atau")) { + string mu=xPara->FirstChildElement("atau")->Attribute("mu"); + string sigma=xPara->FirstChildElement("atau")->Attribute("sigma"); + pAtauMu=atof(mu.c_str()); + pAtauSigma=atof(sigma.c_str()); + Log->Write("INFO: \tAtau mu=" +mu +" ,"+ " sigma="+sigma+" "); + } + + //force_ped + if(modelName == "gcfm") { + pModel = 1; + if(xPara->FirstChild("force_ped")) { + string nu=xPara->FirstChildElement("force_ped")->Attribute("nu"); + string dist_max=xPara->FirstChildElement("force_ped")->Attribute("dist_max"); + string disteff_max=xPara->FirstChildElement("force_ped")->Attribute("disteff_max"); + string interpolation_width=xPara->FirstChildElement("force_ped")->Attribute("interpolation_width"); + + pMaxFPed=atof(dist_max.c_str()); + pNuPed=atof(nu.c_str()); + pDistEffMaxPed=atof(disteff_max.c_str()); + pIntPWidthPed=atof(interpolation_width.c_str()); + Log->Write("INFO: \tfrep_ped mu=" +nu +", dist_max="+dist_max+", disteff_max=" + + disteff_max+ ", interpolation_width="+interpolation_width); + } + + //force_wall + if(xPara->FirstChild("force_wall")) { + string nu=xPara->FirstChildElement("force_wall")->Attribute("nu"); + string dist_max=xPara->FirstChildElement("force_wall")->Attribute("dist_max"); + string disteff_max=xPara->FirstChildElement("force_wall")->Attribute("disteff_max"); + string interpolation_width=xPara->FirstChildElement("force_wall")->Attribute("interpolation_width"); + pMaxFWall=atof(dist_max.c_str()); + pNuWall=atof(nu.c_str()); + pDistEffMaxWall=atof(disteff_max.c_str()); + pIntPWidthWall=atof(interpolation_width.c_str()); + Log->Write("INFO: \tfrep_wall mu=" +nu +", dist_max="+dist_max+", disteff_max=" + + disteff_max+ ", interpolation_width="+interpolation_width); + } + }//if gcfm + else if(modelName == "gompertz") { + pModel = 2; + //force_ped + if(xPara->FirstChild("force_ped")) { + string nu=xPara->FirstChildElement("force_ped")->Attribute("nu"); + pNuPed=atof(nu.c_str()); + Log->Write("INFO: \tfrep_ped mu=" +nu); + + } + //force_wall + if(xPara->FirstChild("force_wall")) { + string nu=xPara->FirstChildElement("force_wall")->Attribute("nu"); + pNuWall=atof(nu.c_str()); + Log->Write("INFO: \tfrep_wall mu=" +nu); + } + } + }//gcfm + else { + Log->Write("INFO: \tno gcfm parameter values found"); + } + + + //route choice strategy + TiXmlNode* xRouters=xMainNode->FirstChild("route_choice_models"); + + if(!xRouters) { + Log->Write("ERROR:\tNo routers found."); + exit(EXIT_FAILURE); + } + + for(TiXmlElement* e = xRouters->FirstChildElement("router"); e; + e = e->NextSiblingElement("router")) { + + string strategy=e->Attribute("description"); + int id=atoi(e->Attribute("router_id")); + + if(strategy=="local_shortest") + pRoutingStrategies.push_back(make_pair(id,ROUTING_LOCAL_SHORTEST)); + else if(strategy=="global_shortest") + pRoutingStrategies.push_back(make_pair(id,ROUTING_GLOBAL_SHORTEST)); + else if(strategy=="quickest") + pRoutingStrategies.push_back(make_pair(id,ROUTING_QUICKEST)); + else if(strategy=="dynamic") + pRoutingStrategies.push_back(make_pair(id,ROUTING_DYNAMIC)); + else if(strategy=="nav_mesh") + pRoutingStrategies.push_back(make_pair(id,ROUTING_NAV_MESH)); + else if(strategy=="dummy") + pRoutingStrategies.push_back(make_pair(id,ROUTING_DUMMY)); + else if(strategy=="global_safest") + pRoutingStrategies.push_back(make_pair(id,ROUTING_SAFEST)); + else if(strategy=="cognitive_map") + pRoutingStrategies.push_back(make_pair(id,ROUTING_COGNITIVEMAP)); + else { + Log->Write("ERROR: \twrong value for routing strategy [%s]!!!\n",strategy.c_str()); + exit(EXIT_FAILURE); + } + } + + Log->Write("INFO: \tParsing the project file completed"); +} + + +int ArgumentParser::GetModel() const +{ + return pModel; +} +const FileFormat& ArgumentParser::GetFileFormat() const +{ + return pFormat; +} +const string& ArgumentParser::GetHostname() const +{ + return pHostname; +} +void ArgumentParser::SetHostname(const string& hostname) +{ + pHostname = hostname; +} +int ArgumentParser::GetPort() const +{ + return pPort; +} +void ArgumentParser::SetPort(int port) +{ + pPort = port; +} +int ArgumentParser::GetSolver() const +{ + return pSolver; +} + +double ArgumentParser::GetTmax() const +{ + return pTmax; +} + +double ArgumentParser::Getdt() const +{ + return pdt; +} + +double ArgumentParser::Getfps() const +{ + return pfps; } -const string& ArgumentParser::GetProjectFile() const { - return _projectFile; +const string& ArgumentParser::GetProjectFile() const +{ + return _projectFile; } /// @deprecated -const string& ArgumentParser::GetNavigationMesh() const { - return pNavMeshFilename; +const string& ArgumentParser::GetNavigationMesh() const +{ + return pNavMeshFilename; } -int ArgumentParser::GetExitStrategy() const { - return pExitStrategy; +int ArgumentParser::GetExitStrategy() const +{ + return pExitStrategy; } -bool ArgumentParser::GetLinkedCells() const { - return pLinkedCells; +bool ArgumentParser::GetLinkedCells() const +{ + return pLinkedCells; } -vector< pair<int, RoutingStrategy> > ArgumentParser::GetRoutingStrategy() const { - return pRoutingStrategies; +vector< pair<int, RoutingStrategy> > ArgumentParser::GetRoutingStrategy() const +{ + return pRoutingStrategies; } -double ArgumentParser::GetV0Mu() const { - return pV0Mu; +double ArgumentParser::GetV0Mu() const +{ + return pV0Mu; } -double ArgumentParser::GetV0Sigma() const { - return pV0Sigma; +double ArgumentParser::GetV0Sigma() const +{ + return pV0Sigma; } -double ArgumentParser::GetBmaxMu() const { - return pBmaxMu; +double ArgumentParser::GetBmaxMu() const +{ + return pBmaxMu; } -double ArgumentParser::GetBmaxSigma() const { - return pBmaxSigma; +double ArgumentParser::GetBmaxSigma() const +{ + return pBmaxSigma; } -double ArgumentParser::GetBminMu() const { - return pBminMu; +double ArgumentParser::GetBminMu() const +{ + return pBminMu; } -double ArgumentParser::GetBminSigma() const { - return pBminSigma; +double ArgumentParser::GetBminSigma() const +{ + return pBminSigma; } -double ArgumentParser::GetAtauMu() const { - return pAtauMu; +double ArgumentParser::GetAtauMu() const +{ + return pAtauMu; } -double ArgumentParser::GetAtauSigma() const { - return pAtauSigma; +double ArgumentParser::GetAtauSigma() const +{ + return pAtauSigma; } -double ArgumentParser::GetAminMu() const { - return pAminMu; +double ArgumentParser::GetAminMu() const +{ + return pAminMu; } -double ArgumentParser::GetAminSigma() const { - return pAminSigma; +double ArgumentParser::GetAminSigma() const +{ + return pAminSigma; } -double ArgumentParser::GetNuPed() const { - return pNuPed; +double ArgumentParser::GetNuPed() const +{ + return pNuPed; } -double ArgumentParser::GetNuWall() const { - return pNuWall; +double ArgumentParser::GetNuWall() const +{ + return pNuWall; } -double ArgumentParser::GetIntPWidthPed() const { - return pIntPWidthPed; +double ArgumentParser::GetIntPWidthPed() const +{ + return pIntPWidthPed; } -double ArgumentParser::GetIntPWidthWall() const { - return pIntPWidthWall; +double ArgumentParser::GetIntPWidthWall() const +{ + return pIntPWidthWall; } -double ArgumentParser::GetMaxFPed() const { - return pMaxFPed; +double ArgumentParser::GetMaxFPed() const +{ + return pMaxFPed; } -double ArgumentParser::GetMaxFWall() const { - return pMaxFWall; +double ArgumentParser::GetMaxFWall() const +{ + return pMaxFWall; } -double ArgumentParser::GetDistEffMaxPed() const { - return pDistEffMaxPed; +double ArgumentParser::GetDistEffMaxPed() const +{ + return pDistEffMaxPed; } -double ArgumentParser::GetDistEffMaxWall() const { - return pDistEffMaxWall; +double ArgumentParser::GetDistEffMaxWall() const +{ + return pDistEffMaxWall; } -double ArgumentParser::GetTauMu() const { - return pTauMu; +double ArgumentParser::GetTauMu() const +{ + return pTauMu; } -double ArgumentParser::GetTauSigma() const { - return pTauSigma; +double ArgumentParser::GetTauSigma() const +{ + return pTauSigma; } -int ArgumentParser::GetLog() const { - return pLog; +int ArgumentParser::GetLog() const +{ + return pLog; } -double ArgumentParser::GetLinkedCellSize() const{ - return pLinkedCellSize; +double ArgumentParser::GetLinkedCellSize() const +{ + return pLinkedCellSize; } -unsigned int ArgumentParser::GetSeed() const { - return pSeed; +unsigned int ArgumentParser::GetSeed() const +{ + return pSeed; } -int ArgumentParser::GetEmbededMesh() const { - return _embedMesh; +int ArgumentParser::GetEmbededMesh() const +{ + return _embedMesh; } -const string& ArgumentParser::GetErrorLogFile() const { - return pErrorLogFile; +const string& ArgumentParser::GetErrorLogFile() const +{ + return pErrorLogFile; } -int ArgumentParser::GetMaxOpenMPThreads() const{ - return pMaxOpenMPThreads; +int ArgumentParser::GetMaxOpenMPThreads() const +{ + return pMaxOpenMPThreads; } -const string& ArgumentParser::GetTrajectoriesFile() const { - return pTrajectoriesFile; +const string& ArgumentParser::GetTrajectoriesFile() const +{ + return pTrajectoriesFile; } -void ArgumentParser::SetTrajectoriesFile(const string& trajectoriesFile) { - pTrajectoriesFile = trajectoriesFile; +void ArgumentParser::SetTrajectoriesFile(const string& trajectoriesFile) +{ + pTrajectoriesFile = trajectoriesFile; } -const string& ArgumentParser::GetProjectRootDir() const { - return _projectRootDir; +const string& ArgumentParser::GetProjectRootDir() const +{ + return _projectRootDir; } diff --git a/general/ArgumentParser.h b/general/ArgumentParser.h index 330cbabfa0fa395e2d650f53c470e2e912e3d866..fd1cf7f6b6d7d8f85d9d66cdea21553b80e52803 100644 --- a/general/ArgumentParser.h +++ b/general/ArgumentParser.h @@ -41,139 +41,139 @@ class OutputHandler; extern OutputHandler* Log; class ArgumentParser { - private: - int pModel; - string pHostname; - string pTrajectoriesFile; - string pErrorLogFile; - string pNavMeshFilename; - string _projectFile; - string _projectRootDir; - double pTmax; // maximale Simulationszeit - double pdt; // Zeitschritt - double pfps; //frame rate - bool pLinkedCells; // use of linked-cells neighbourhood list - double pLinkedCellSize; // cell size of the linkedcell (default to 2.2m) - double pV0Mu; // mu für die Normalverteilung von v0 - double pV0Sigma; // sigma für die Normalverteilung von v0 - double pBmaxMu; // mu für die Normalverteilung von b_max - double pBmaxSigma; // sigma für die Normalverteilung von b_max - double pBminMu; // mu für die Normalverteilung von b_min - double pBminSigma; // sigma für die Normalverteilung von b_min - double pAtauMu; // mu für die Normalverteilung von a_tau - double pAtauSigma; // sigma für die Normalverteilung von a_tau - double pAminMu; // mu für die Normalverteilung von a_min - double pAminSigma; // sigma für die Normalverteilung von a_min - double pTauMu; - double pTauSigma; - double pNuPed; - double pNuWall; - double pIntPWidthPed; - double pIntPWidthWall; - double pMaxFPed; - double pMaxFWall; - double pDistEffMaxPed; - double pDistEffMaxWall; - unsigned int pSeed; - int pSolver; /// solver for the differential equation - int pExitStrategy; // Strategie zur Richtungswahl (v0) - int pLog; - int pPort; - int _embedMesh; - int pMaxOpenMPThreads; - FileFormat pFormat; - vector< pair<int, RoutingStrategy> > pRoutingStrategies; +private: + int pModel; + string pHostname; + string pTrajectoriesFile; + string pErrorLogFile; + string pNavMeshFilename; + string _projectFile; + string _projectRootDir; + double pTmax; // maximale Simulationszeit + double pdt; // Zeitschritt + double pfps; //frame rate + bool pLinkedCells; // use of linked-cells neighbourhood list + double pLinkedCellSize; // cell size of the linkedcell (default to 2.2m) + double pV0Mu; // mu für die Normalverteilung von v0 + double pV0Sigma; // sigma für die Normalverteilung von v0 + double pBmaxMu; // mu für die Normalverteilung von b_max + double pBmaxSigma; // sigma für die Normalverteilung von b_max + double pBminMu; // mu für die Normalverteilung von b_min + double pBminSigma; // sigma für die Normalverteilung von b_min + double pAtauMu; // mu für die Normalverteilung von a_tau + double pAtauSigma; // sigma für die Normalverteilung von a_tau + double pAminMu; // mu für die Normalverteilung von a_min + double pAminSigma; // sigma für die Normalverteilung von a_min + double pTauMu; + double pTauSigma; + double pNuPed; + double pNuWall; + double pIntPWidthPed; + double pIntPWidthWall; + double pMaxFPed; + double pMaxFWall; + double pDistEffMaxPed; + double pDistEffMaxWall; + unsigned int pSeed; + int pSolver; /// solver for the differential equation + int pExitStrategy; // Strategie zur Richtungswahl (v0) + int pLog; + int pPort; + int _embedMesh; + int pMaxOpenMPThreads; + FileFormat pFormat; + vector< pair<int, RoutingStrategy> > pRoutingStrategies; - // private Funktionen - void Usage(); + // private Funktionen + void Usage(); - public: - // Konstruktor - ArgumentParser(); // gibt die Programmoptionen aus +public: + // Konstruktor + ArgumentParser(); // gibt die Programmoptionen aus - // Getter-Funktionen - bool IsOnline() const; - bool GetLinkedCells() const; - int GetModel() const; - int GetSolver() const; - int GetExitStrategy() const; - int GetRandomize() const; - int GetMaxOpenMPThreads() const; - int GetLog() const; - int GetTravisto() const; - int GetTrajektorien() const; - int GetPort() const; - int GetEmbededMesh() const ; - unsigned int GetSeed() const; + // Getter-Funktionen + bool IsOnline() const; + bool GetLinkedCells() const; + int GetModel() const; + int GetSolver() const; + int GetExitStrategy() const; + int GetRandomize() const; + int GetMaxOpenMPThreads() const; + int GetLog() const; + int GetTravisto() const; + int GetTrajektorien() const; + int GetPort() const; + int GetEmbededMesh() const ; + unsigned int GetSeed() const; - double Getfps() const; - double GetLinkedCellSize() const; - double GetTmax() const; - double Getdt() const; - double GetV0Mu() const; - double GetV0Sigma() const; - double GetBmaxMu() const; - double GetBmaxSigma() const; - double GetBminMu() const; - double GetBminSigma() const; - double GetAtauMu() const; - double GetAtauSigma() const; - double GetAminMu() const; - double GetAminSigma() const; - double GetNuPed() const; - double GetNuWall() const; - double GetIntPWidthPed() const; - double GetIntPWidthWall() const; - double GetMaxFPed() const; - double GetMaxFWall() const; - double GetDistEffMaxPed() const; - double GetDistEffMaxWall() const; - double GetTauMu() const; - double GetTauSigma() const; - void SetHostname(const string& hostname); - void SetPort(int port); - void SetTrajectoriesFile(const string& trajectoriesFile); + double Getfps() const; + double GetLinkedCellSize() const; + double GetTmax() const; + double Getdt() const; + double GetV0Mu() const; + double GetV0Sigma() const; + double GetBmaxMu() const; + double GetBmaxSigma() const; + double GetBminMu() const; + double GetBminSigma() const; + double GetAtauMu() const; + double GetAtauSigma() const; + double GetAminMu() const; + double GetAminSigma() const; + double GetNuPed() const; + double GetNuWall() const; + double GetIntPWidthPed() const; + double GetIntPWidthWall() const; + double GetMaxFPed() const; + double GetMaxFWall() const; + double GetDistEffMaxPed() const; + double GetDistEffMaxWall() const; + double GetTauMu() const; + double GetTauSigma() const; + void SetHostname(const string& hostname); + void SetPort(int port); + void SetTrajectoriesFile(const string& trajectoriesFile); - const string& GetHostname() const; - const string& GetTrajectoriesFile() const; - const string& GetErrorLogFile() const; - const string& GetTrafficFile() const; - const string& GetRoutingFile() const; - const string& GetPersonsFilename() const; - const string& GetPathwayFile() const; - const string& GetGeometryFilename() const; - const string& GetNavigationMesh() const; - const string& GetProjectFile() const; - const string& GetProjectRootDir() const; + const string& GetHostname() const; + const string& GetTrajectoriesFile() const; + const string& GetErrorLogFile() const; + const string& GetTrafficFile() const; + const string& GetRoutingFile() const; + const string& GetPersonsFilename() const; + const string& GetPathwayFile() const; + const string& GetGeometryFilename() const; + const string& GetNavigationMesh() const; + const string& GetProjectFile() const; + const string& GetProjectRootDir() const; - vector< pair<int, RoutingStrategy> > GetRoutingStrategy() const; - const FileFormat& GetFileFormat() const; + vector< pair<int, RoutingStrategy> > GetRoutingStrategy() const; + const FileFormat& GetFileFormat() const; - /** - * Parse the commands passed to the command line - * specially looks for the initialization file - */ - void ParseArgs(int argc, char **argv); + /** + * Parse the commands passed to the command line + * specially looks for the initialization file + */ + void ParseArgs(int argc, char **argv); - /** - * Parse the initialization file - * @param inifile - */ - void ParseIniFile(string inifile); + /** + * Parse the initialization file + * @param inifile + */ + void ParseIniFile(string inifile); - /** - * convert a non null string to int. - */ - void Str2Int(const char* str, int* value){ - if(!str) *value=atoi(str); - }; + /** + * convert a non null string to int. + */ + void Str2Int(const char* str, int* value) { + if(!str) *value=atoi(str); + }; - /** - * convert a non null string to double. - */ - void Str2double(const char* str, double* value){ - if(!str) *value=atof(str); - }; + /** + * convert a non null string to double. + */ + void Str2double(const char* str, double* value) { + if(!str) *value=atof(str); + }; }; diff --git a/general/Macros.h b/general/Macros.h index b5685dbafa618d8727b1b699ad1e079daa443e84..29a9d3c94ffadaa839def4161e1fda539b9fa00f 100644 --- a/general/Macros.h +++ b/general/Macros.h @@ -74,40 +74,64 @@ enum RoomState { - ROOM_CLEAN=0, - ROOM_SMOKED=1 + ROOM_CLEAN=0, + ROOM_SMOKED=1 }; enum FileFormat { - FORMAT_XML_PLAIN, - FORMAT_XML_BIN, - FORMAT_PLAIN, - FORMAT_VTK, - FORMAT_XML_PLAIN_WITH_MESH + FORMAT_XML_PLAIN, + FORMAT_XML_BIN, + FORMAT_PLAIN, + FORMAT_VTK, + FORMAT_XML_PLAIN_WITH_MESH }; enum RoutingStrategy { - ROUTING_LOCAL_SHORTEST, - ROUTING_GLOBAL_SHORTEST, - ROUTING_QUICKEST, - ROUTING_DYNAMIC, - ROUTING_FROM_FILE, - ROUTING_NAV_MESH, - ROUTING_DUMMY, - ROUTING_SAFEST, - ROUTING_COGNITIVEMAP, - ROUTING_UNDEFINED =-1 + ROUTING_LOCAL_SHORTEST, + ROUTING_GLOBAL_SHORTEST, + ROUTING_QUICKEST, + ROUTING_DYNAMIC, + ROUTING_FROM_FILE, + ROUTING_NAV_MESH, + ROUTING_DUMMY, + ROUTING_SAFEST, + ROUTING_COGNITIVEMAP, + ROUTING_UNDEFINED =-1 }; //global functions for convenience -inline char xmltob(const char * t,char v=0){ if (t&&(*t)) return (char)atoi(t); return v; } -inline int xmltoi(const char * t,int v=0){ if (t&&(*t)) return atoi(t); return v; } -inline long xmltol(const char * t,long v=0){ if (t&&(*t)) return atol(t); return v; } -inline double xmltof(const char * t,double v=0.0){ if (t&&(*t)) return atof(t); return v; } -inline const char * xmltoa(const char * t, const char * v=""){ if (t) return t; return v; } -inline char xmltoc(const char * t,const char v='\0'){ if (t&&(*t)) return *t; return v; } +inline char xmltob(const char * t,char v=0) +{ + if (t&&(*t)) return (char)atoi(t); + return v; +} +inline int xmltoi(const char * t,int v=0) +{ + if (t&&(*t)) return atoi(t); + return v; +} +inline long xmltol(const char * t,long v=0) +{ + if (t&&(*t)) return atol(t); + return v; +} +inline double xmltof(const char * t,double v=0.0) +{ + if (t&&(*t)) return atof(t); + return v; +} +inline const char * xmltoa(const char * t, const char * v="") +{ + if (t) return t; + return v; +} +inline char xmltoc(const char * t,const char v='\0') +{ + if (t&&(*t)) return *t; + return v; +} #endif /* _MACROS_H */ diff --git a/geometry/Building.cpp b/geometry/Building.cpp index 7c312dda49140b8695463b296ab2d058557c7394..8fd5bf5763106d02954237ec4e3f6fe7823aad4c 100644 --- a/geometry/Building.cpp +++ b/geometry/Building.cpp @@ -51,1455 +51,1508 @@ using namespace std; Konstruktoren ************************************************************/ -Building::Building() { - _caption = "no_caption"; - _projectFilename = ""; - _geometryFilename= ""; - _rooms = vector<Room*>(); - _routingEngine = NULL; - _linkedCellGrid = NULL; - _savePathway = false; +Building::Building() +{ + _caption = "no_caption"; + _projectFilename = ""; + _geometryFilename= ""; + _rooms = vector<Room*>(); + _routingEngine = NULL; + _linkedCellGrid = NULL; + _savePathway = false; } -Building::~Building() { - for (int i = 0; i < GetNumberOfRooms(); i++) - delete _rooms[i]; +Building::~Building() +{ + for (int i = 0; i < GetNumberOfRooms(); i++) + delete _rooms[i]; #ifdef _SIMULATOR - delete _routingEngine; - delete _linkedCellGrid; + delete _routingEngine; + delete _linkedCellGrid; #endif - if (_pathWayStream.is_open()) - _pathWayStream.close(); - - - for (map<int, Crossing*>::const_iterator iter = _crossings.begin(); - iter != _crossings.end(); ++iter) { - delete iter->second; - } - for (map<int, Transition*>::const_iterator iter = _transitions.begin(); - iter != _transitions.end(); ++iter) { - delete iter->second; - } - for (map<int, Hline*>::const_iterator iter = _hLines.begin(); - iter != _hLines.end(); ++iter) { - delete iter->second; - } - for (map<int, Goal*>::const_iterator iter = _goals.begin(); - iter != _goals.end(); ++iter) { - delete iter->second; - } + if (_pathWayStream.is_open()) + _pathWayStream.close(); + + + for (map<int, Crossing*>::const_iterator iter = _crossings.begin(); + iter != _crossings.end(); ++iter) { + delete iter->second; + } + for (map<int, Transition*>::const_iterator iter = _transitions.begin(); + iter != _transitions.end(); ++iter) { + delete iter->second; + } + for (map<int, Hline*>::const_iterator iter = _hLines.begin(); + iter != _hLines.end(); ++iter) { + delete iter->second; + } + for (map<int, Goal*>::const_iterator iter = _goals.begin(); + iter != _goals.end(); ++iter) { + delete iter->second; + } } /************************************************************ Setter-Funktionen ************************************************************/ -void Building::SetCaption(const std::string& s) { - _caption = s; +void Building::SetCaption(const std::string& s) +{ + _caption = s; } -void Building::SetRoutingEngine(RoutingEngine* r) { - _routingEngine = r; +void Building::SetRoutingEngine(RoutingEngine* r) +{ + _routingEngine = r; } -void Building::SetRoom(Room* room, int index) { - if ((index >= 0) && (index < (int) _rooms.size())) { - _rooms[index] = room; - } else { - Log->Write("ERROR: \tWrong Index in CBuilding::SetRoom()"); - exit(0); - } +void Building::SetRoom(Room* room, int index) +{ + if ((index >= 0) && (index < (int) _rooms.size())) { + _rooms[index] = room; + } else { + Log->Write("ERROR: \tWrong Index in CBuilding::SetRoom()"); + exit(0); + } } /************************************************************* Getter-Funktionen ************************************************************/ -string Building::GetCaption() const { - return _caption; +string Building::GetCaption() const +{ + return _caption; } -RoutingEngine* Building::GetRoutingEngine() const { - return _routingEngine; +RoutingEngine* Building::GetRoutingEngine() const +{ + return _routingEngine; } -int Building::GetNumberOfRooms() const { - return _rooms.size(); +int Building::GetNumberOfRooms() const +{ + return _rooms.size(); } -int Building::GetNumberOfGoals() const { - return _transitions.size() + _hLines.size() + _crossings.size(); +int Building::GetNumberOfGoals() const +{ + return _transitions.size() + _hLines.size() + _crossings.size(); } -const vector<Room*>& Building::GetAllRooms() const { - return _rooms; +const vector<Room*>& Building::GetAllRooms() const +{ + return _rooms; } -Room* Building::GetRoom(int index) const { - if ((index >= 0) && (index < (int) _rooms.size())) { - return _rooms[index]; - } else { - Log->Write("ERROR: Wrong 'index' in CBuiling::GetRoom() Room ID: %d size: %d",index, _rooms.size()); - Log->Write("ERROR: Control your rooms ID and make sure they are in the order 0, 1, 2,.. "); - exit(EXIT_FAILURE); - } +Room* Building::GetRoom(int index) const +{ + if ((index >= 0) && (index < (int) _rooms.size())) { + return _rooms[index]; + } else { + Log->Write("ERROR: Wrong 'index' in CBuiling::GetRoom() Room ID: %d size: %d",index, _rooms.size()); + Log->Write("ERROR: Control your rooms ID and make sure they are in the order 0, 1, 2,.. "); + exit(EXIT_FAILURE); + } } -LCGrid* Building::GetGrid() const { - return _linkedCellGrid; +LCGrid* Building::GetGrid() const +{ + return _linkedCellGrid; } -void Building::AddRoom(Room* room) { - _rooms.push_back(room); +void Building::AddRoom(Room* room) +{ + _rooms.push_back(room); } -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 - for (unsigned int r = 0; r < _rooms.size(); r++) { - Room* room = _rooms[r]; - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - const vector<Wall>& allWalls = sub->GetAllWalls(); - - for (unsigned int a = 0; a < allWalls.size(); a++) { - double x1 = allWalls[a].GetPoint1().GetX(); - double y1 = allWalls[a].GetPoint1().GetY(); - double x2 = allWalls[a].GetPoint2().GetX(); - double y2 = allWalls[a].GetPoint2().GetY(); - - double xmax = (x1 > x2) ? x1 : x2; - double xmin = (x1 > x2) ? x2 : x1; - double ymax = (y1 > y2) ? y1 : y2; - double ymin = (y1 > y2) ? y2 : y1; - - 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; - } - } - } - - for (map<int, Goal*>::const_iterator itr = _goals.begin(); - itr != _goals.end(); ++itr) { - - const vector<Wall>& allWalls = itr->second->GetAllWalls(); - - for (unsigned int a = 0; a < allWalls.size(); a++) { - double x1 = allWalls[a].GetPoint1().GetX(); - double y1 = allWalls[a].GetPoint1().GetY(); - double x2 = allWalls[a].GetPoint2().GetX(); - double y2 = allWalls[a].GetPoint2().GetY(); - - double xmax = (x1 > x2) ? x1 : x2; - double xmin = (x1 > x2) ? x2 : x1; - double ymax = (y1 > y2) ? y1 : y2; - double ymin = (y1 > y2) ? y2 : y1; - - 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; - } - } - - //make the grid slightly larger. - x_min = x_min - 10.0; - x_max = x_max + 10.0; - y_min = y_min - 10.0; - y_max = y_max + 10.0; - - SubRoom* bigSubroom = new NormalSubRoom(); - bigSubroom->SetRoomID(_rooms.size()); - 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))); - - Room * bigRoom = new Room(); - bigRoom->AddSubRoom(bigSubroom); - bigRoom->SetCaption("outside"); - bigRoom->SetID(_rooms.size()); - AddRoom(bigRoom); +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 + for (unsigned int r = 0; r < _rooms.size(); r++) { + Room* room = _rooms[r]; + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + const vector<Wall>& allWalls = sub->GetAllWalls(); + + for (unsigned int a = 0; a < allWalls.size(); a++) { + double x1 = allWalls[a].GetPoint1().GetX(); + double y1 = allWalls[a].GetPoint1().GetY(); + double x2 = allWalls[a].GetPoint2().GetX(); + double y2 = allWalls[a].GetPoint2().GetY(); + + double xmax = (x1 > x2) ? x1 : x2; + double xmin = (x1 > x2) ? x2 : x1; + double ymax = (y1 > y2) ? y1 : y2; + double ymin = (y1 > y2) ? y2 : y1; + + 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; + } + } + } + + for (map<int, Goal*>::const_iterator itr = _goals.begin(); + itr != _goals.end(); ++itr) { + + const vector<Wall>& allWalls = itr->second->GetAllWalls(); + + for (unsigned int a = 0; a < allWalls.size(); a++) { + double x1 = allWalls[a].GetPoint1().GetX(); + double y1 = allWalls[a].GetPoint1().GetY(); + double x2 = allWalls[a].GetPoint2().GetX(); + double y2 = allWalls[a].GetPoint2().GetY(); + + double xmax = (x1 > x2) ? x1 : x2; + double xmin = (x1 > x2) ? x2 : x1; + double ymax = (y1 > y2) ? y1 : y2; + double ymin = (y1 > y2) ? y2 : y1; + + 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; + } + } + + //make the grid slightly larger. + x_min = x_min - 10.0; + x_max = x_max + 10.0; + y_min = y_min - 10.0; + y_max = y_max + 10.0; + + SubRoom* bigSubroom = new NormalSubRoom(); + bigSubroom->SetRoomID(_rooms.size()); + 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))); + + Room * bigRoom = new Room(); + bigRoom->AddSubRoom(bigSubroom); + bigRoom->SetCaption("outside"); + bigRoom->SetID(_rooms.size()); + AddRoom(bigRoom); } -void Building::InitGeometry() { - Log->Write("INFO: \tInit Geometry"); - for (int i = 0; i < GetNumberOfRooms(); i++) { - Room* room = GetRoom(i); - // Polygone berechnen - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* s = room->GetSubRoom(j); - // Alle Übergänge in diesem Raum bestimmen - // Übergänge müssen zu Wänden ergänzt werden - vector<Line*> goals = vector<Line*>(); - - // crossings - const vector<Crossing*>& crossings = s->GetAllCrossings(); - for (unsigned int i = 0; i < crossings.size(); i++) { - goals.push_back(crossings[i]); - } - - // and transitions - const vector<Transition*>& transitions = s->GetAllTransitions(); - for (unsigned int i = 0; i < transitions.size(); i++) { - goals.push_back(transitions[i]); - } - - // initialize the poly - s->ConvertLineToPoly(goals); - s->CalculateArea(); - goals.clear(); - - //do the same for the obstacles that are closed - const vector<Obstacle*>& obstacles = s->GetAllObstacles(); - for (unsigned int obs = 0; obs < obstacles.size(); ++obs) { - if (obstacles[obs]->GetClosed() == 1) - obstacles[obs]->ConvertLineToPoly(); - } - } - } - Log->Write("INFO: \tInit Geometry successful!!!\n"); +void Building::InitGeometry() +{ + Log->Write("INFO: \tInit Geometry"); + for (int i = 0; i < GetNumberOfRooms(); i++) { + Room* room = GetRoom(i); + // Polygone berechnen + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* s = room->GetSubRoom(j); + // Alle Übergänge in diesem Raum bestimmen + // Übergänge müssen zu Wänden ergänzt werden + vector<Line*> goals = vector<Line*>(); + + // crossings + const vector<Crossing*>& crossings = s->GetAllCrossings(); + for (unsigned int i = 0; i < crossings.size(); i++) { + goals.push_back(crossings[i]); + } + + // and transitions + const vector<Transition*>& transitions = s->GetAllTransitions(); + for (unsigned int i = 0; i < transitions.size(); i++) { + goals.push_back(transitions[i]); + } + + // initialize the poly + s->ConvertLineToPoly(goals); + s->CalculateArea(); + goals.clear(); + + //do the same for the obstacles that are closed + const vector<Obstacle*>& obstacles = s->GetAllObstacles(); + for (unsigned int obs = 0; obs < obstacles.size(); ++obs) { + if (obstacles[obs]->GetClosed() == 1) + obstacles[obs]->ConvertLineToPoly(); + } + } + } + Log->Write("INFO: \tInit Geometry successful!!!\n"); } -const string& Building::GetProjectFilename() const{ - return _projectFilename; +const string& Building::GetProjectFilename() const +{ + return _projectFilename; } -void Building::SetProjectFilename(const std::string &filename){ - _projectFilename=filename; +void Building::SetProjectFilename(const std::string &filename) +{ + _projectFilename=filename; } -void Building::SetProjectRootDir(const std::string &filename){ - _projectRootDir= filename; +void Building::SetProjectRootDir(const std::string &filename) +{ + _projectRootDir= filename; } -const string& Building::GetProjectRootDir() const{ - return _projectRootDir; +const string& Building::GetProjectRootDir() const +{ + return _projectRootDir; } -const std::string& Building::GetGeometryFilename() const { - return _geometryFilename; +const std::string& Building::GetGeometryFilename() const +{ + return _geometryFilename; } -void Building::LoadBuildingFromFile() { - - //get the geometry filename from the project file - TiXmlDocument doc(_projectFilename); - if (!doc.LoadFile()){ - Log->Write("ERROR: \t%s", doc.ErrorDesc()); - Log->Write("ERROR: \t could not parse the project file"); - exit(EXIT_FAILURE); - } - - Log->Write("INFO: \tParsing the geometry file"); - TiXmlElement* xMainNode = doc.RootElement(); - string geoFilenameWithPath=""; - if(xMainNode->FirstChild("geometry")){ - _geometryFilename=xMainNode->FirstChild("geometry")->FirstChild()->Value(); - geoFilenameWithPath=_projectRootDir+_geometryFilename; - Log->Write("INFO: \tgeometry <"+_geometryFilename+">"); - } - - TiXmlDocument docGeo(geoFilenameWithPath); - if (!docGeo.LoadFile()){ - Log->Write("ERROR: \t%s", docGeo.ErrorDesc()); - Log->Write("ERROR: \t could not parse the geometry file"); - exit(EXIT_FAILURE); - } - - TiXmlElement* xRootNode = docGeo.RootElement(); - if( ! xRootNode ) { - Log->Write("ERROR:\tRoot element does not exist"); - exit(EXIT_FAILURE); - } - - if( xRootNode->ValueStr () != "geometry" ) { - Log->Write("ERROR:\tRoot element value is not 'geometry'."); - exit(EXIT_FAILURE); - } - - if(string(xRootNode->Attribute("unit"))!="m") { - Log->Write("ERROR:\tOnly the unit m (metres) is supported. \n\tYou supplied [%s]",xRootNode->Attribute("unit")); - exit(EXIT_FAILURE); - } - - double version = xmltof(xRootNode->Attribute("version"), -1); - if (version != 0.5) { - Log->Write("ERROR: \tWrong goemetry version!"); - Log->Write("ERROR: \tOnly version >= %s supported",JPS_VERSION); - Log->Write("ERROR: \tPlease update the version of your geometry file to %s",JPS_VERSION); - exit(EXIT_FAILURE); - } - _caption = xmltoa(xRootNode->Attribute("caption"), "virtual building"); - - - //The file has two main nodes - //<rooms> and <transitions> - - - //processing the rooms node - TiXmlNode* xRoomsNode = xRootNode->FirstChild("rooms"); - if (!xRoomsNode){ - Log->Write("ERROR: \tThe geometry should have at least one room and one subroom"); - exit(EXIT_FAILURE); - } - - for(TiXmlElement* xRoom = xRoomsNode->FirstChildElement("room"); xRoom; - xRoom = xRoom->NextSiblingElement("room")) { - - Room* room = new Room(); - - string room_id = xmltoa(xRoom->Attribute("id"), "-1"); - room->SetID(xmltoi(room_id.c_str(), -1)); - - string caption = "room " + room_id; - room->SetCaption( - xmltoa(xRoom->Attribute("caption"), caption.c_str())); - - double position = xmltof(xRoom->Attribute("zpos"), 0.0); - - //TODO?? what the hell is that for ? - //if(position>6.0) position+=50; - room->SetZPos(position); - - //parsing the subrooms - //processing the rooms node - //TiXmlNode* xSubroomsNode = xRoom->FirstChild("subroom"); - - for(TiXmlElement* xSubRoom = xRoom->FirstChildElement("subroom"); xSubRoom; - xSubRoom = xSubRoom->NextSiblingElement("subroom")) { - - - string subroom_id = xmltoa(xSubRoom->Attribute("id"), "-1"); - string closed = xmltoa(xSubRoom->Attribute("closed"), "0"); - string type = xmltoa(xSubRoom->Attribute("class"),"subroom"); - - //get the equation of the plane if any - double A_x = xmltof(xSubRoom->Attribute("A_x"), 0.0); - double B_y = xmltof(xSubRoom->Attribute("B_y"), 0.0); - double C_z = xmltof(xSubRoom->Attribute("C_z"), 0.0); - - SubRoom* subroom = NULL; - - if (type == "stair") { - if(xSubRoom->FirstChildElement("up")==NULL){ - Log->Write("ERROR:\t the attribute <up> and <down> are missing for the stair"); - Log->Write("ERROR:\t check your geometry file"); - exit(EXIT_FAILURE); - } - double up_x = xmltof( xSubRoom->FirstChildElement("up")->Attribute("px"), 0.0); - double up_y = xmltof( xSubRoom->FirstChildElement("up")->Attribute("py"), 0.0); - double down_x = xmltof( xSubRoom->FirstChildElement("down")->Attribute("py"), 0.0); - double down_y = xmltof( xSubRoom->FirstChildElement("down")->Attribute("py"), 0.0); - subroom = new Stair(); - ((Stair*)subroom)->SetUp(Point(up_x,up_y)); - ((Stair*)subroom)->SetDown(Point(down_x,down_y)); - } else { - //normal subroom or corridor - subroom = new NormalSubRoom(); - } - - subroom->SetType(type); - subroom->SetPlanEquation(A_x,B_y,C_z); - subroom->SetRoomID(room->GetID()); - subroom->SetSubRoomID(xmltoi(subroom_id.c_str(), -1)); - - //looking for polygons (walls) - for(TiXmlElement* xPolyVertices = xSubRoom->FirstChildElement("polygon"); xPolyVertices; - xPolyVertices = xPolyVertices->NextSiblingElement("polygon")) { - - for (TiXmlElement* xVertex = xPolyVertices->FirstChildElement( - "vertex"); - xVertex && xVertex != xPolyVertices->LastChild("vertex"); - xVertex = xVertex->NextSiblingElement("vertex")) { - - double x1 = xmltof(xVertex->Attribute("px")); - double y1 = xmltof(xVertex->Attribute("py")); - double x2 = xmltof(xVertex->NextSiblingElement("vertex")->Attribute("px")); - double y2 = xmltof(xVertex->NextSiblingElement("vertex")->Attribute("py")); - - subroom->AddWall(Wall(Point(x1, y1), Point(x2, y2))); - } - - } - - //looking for obstacles - for(TiXmlElement* xObstacle = xSubRoom->FirstChildElement("obstacle"); xObstacle; - xObstacle = xObstacle->NextSiblingElement("obstacle")) { - - int id = xmltof(xObstacle->Attribute("id"), -1); - int height = xmltof(xObstacle->Attribute("height"), 0); - double closed = xmltof(xObstacle->Attribute("closed"), 0); - string caption = xmltoa(xObstacle->Attribute("caption"),"-1"); - - Obstacle* obstacle = new Obstacle(); - obstacle->SetId(id); - obstacle->SetCaption(caption); - obstacle->SetClosed(closed); - obstacle->SetHeight(height); - - //looking for polygons (walls) - for(TiXmlElement* xPolyVertices = xObstacle->FirstChildElement("polygon"); xPolyVertices; - xPolyVertices = xPolyVertices->NextSiblingElement("polygon")) { - - for (TiXmlElement* xVertex = xPolyVertices->FirstChildElement( - "vertex"); - xVertex && xVertex != xPolyVertices->LastChild("vertex"); - xVertex = xVertex->NextSiblingElement("vertex")) { - - double x1 = xmltof(xVertex->Attribute("px")); - double y1 = xmltof(xVertex->Attribute("py")); - double x2 = xmltof(xVertex->NextSiblingElement("vertex")->Attribute("px")); - double y2 = xmltof(xVertex->NextSiblingElement("vertex")->Attribute("py")); - obstacle->AddWall(Wall(Point(x1, y1), Point(x2, y2))); - } - } - subroom->AddObstacle(obstacle); - } - room->AddSubRoom(subroom); - } - - //parsing the crossings - TiXmlNode* xCrossingsNode = xRoom->FirstChild("crossings"); - if(xCrossingsNode) - for(TiXmlElement* xCrossing = xCrossingsNode->FirstChildElement("crossing"); xCrossing; - xCrossing = xCrossing->NextSiblingElement("crossing")) { - - int id = xmltoi(xCrossing->Attribute("id"), -1); - int sub1_id = xmltoi(xCrossing->Attribute("subroom1_id"), -1); - int sub2_id = xmltoi(xCrossing->Attribute("subroom2_id"), -1); - - double x1 = xmltof( xCrossing->FirstChildElement("vertex")->Attribute("px")); - double y1 = xmltof( xCrossing->FirstChildElement("vertex")->Attribute("py")); - double x2 = xmltof( xCrossing->LastChild("vertex")->ToElement()->Attribute("px")); - double y2 = xmltof( xCrossing->LastChild("vertex")->ToElement()->Attribute("py")); - - Crossing* c = new Crossing(); - c->SetID(id); - c->SetPoint1(Point(x1, y1)); - c->SetPoint2(Point(x2, y2)); - - c->SetSubRoom1(room->GetSubRoom(sub1_id)); - c->SetSubRoom2(room->GetSubRoom(sub2_id)); - c->SetRoom1(room); - AddCrossing(c); - - room->GetSubRoom(sub1_id)->AddCrossing(c); - room->GetSubRoom(sub2_id)->AddCrossing(c); - } - - AddRoom(room); - } - - - // all rooms are read, now proceed with transitions - TiXmlNode* xTransNode = xRootNode->FirstChild("transitions"); - if(xTransNode) - for(TiXmlElement* xTrans = xTransNode->FirstChildElement("transition"); xTrans; - xTrans = xTrans->NextSiblingElement("transition")) { - - int id = xmltoi(xTrans->Attribute("id"), -1); - string caption = "door " + id; - caption = xmltoa(xTrans->Attribute("caption"), caption.c_str()); - int room1_id = xmltoi(xTrans->Attribute("room1_id"), -1); - int room2_id = xmltoi(xTrans->Attribute("room2_id"), -1); - int subroom1_id = xmltoi(xTrans->Attribute("subroom1_id"), -1); - int subroom2_id = xmltoi(xTrans->Attribute("subroom2_id"), -1); - string type = xmltoa(xTrans->Attribute("type"), "normal"); - - double x1 = xmltof( xTrans->FirstChildElement("vertex")->Attribute("px")); - double y1 = xmltof( xTrans->FirstChildElement("vertex")->Attribute("py")); - - double x2 = xmltof( xTrans->LastChild("vertex")->ToElement()->Attribute("px")); - double y2 = xmltof( xTrans->LastChild("vertex")->ToElement()->Attribute("py")); - - - Transition* t = new Transition(); - t->SetID(id); - t->SetCaption(caption); - t->SetPoint1(Point(x1, y1)); - t->SetPoint2(Point(x2, y2)); - t->SetType(type); - - if (room1_id != -1 && subroom1_id != -1) { - //Room* room = _rooms[room1_id]; - Room* room = GetRoom(room1_id); - SubRoom* subroom = room->GetSubRoom(subroom1_id); - - //subroom->AddGoalID(t->GetUniqueID()); - //MPI - room->AddTransitionID(t->GetUniqueID()); - t->SetRoom1(room); - t->SetSubRoom1(subroom); - - //new implementation - subroom->AddTransition(t); - } - if (room2_id != -1 && subroom2_id != -1) { - Room* room = _rooms[room2_id]; - SubRoom* subroom = room->GetSubRoom(subroom2_id); - //subroom->AddGoalID(t->GetUniqueID()); - //MPI - room->AddTransitionID(t->GetUniqueID()); - t->SetRoom2(room); - t->SetSubRoom2(subroom); - - //new implementation - subroom->AddTransition(t); - } - - AddTransition(t); - } - - - Log->Write("INFO: \tLoading building file successful!!!\n"); +void Building::LoadBuildingFromFile() +{ + + //get the geometry filename from the project file + TiXmlDocument doc(_projectFilename); + if (!doc.LoadFile()) { + Log->Write("ERROR: \t%s", doc.ErrorDesc()); + Log->Write("ERROR: \t could not parse the project file"); + exit(EXIT_FAILURE); + } + + Log->Write("INFO: \tParsing the geometry file"); + TiXmlElement* xMainNode = doc.RootElement(); + string geoFilenameWithPath=""; + if(xMainNode->FirstChild("geometry")) { + _geometryFilename=xMainNode->FirstChild("geometry")->FirstChild()->Value(); + geoFilenameWithPath=_projectRootDir+_geometryFilename; + Log->Write("INFO: \tgeometry <"+_geometryFilename+">"); + } + + TiXmlDocument docGeo(geoFilenameWithPath); + if (!docGeo.LoadFile()) { + Log->Write("ERROR: \t%s", docGeo.ErrorDesc()); + Log->Write("ERROR: \t could not parse the geometry file"); + exit(EXIT_FAILURE); + } + + TiXmlElement* xRootNode = docGeo.RootElement(); + if( ! xRootNode ) { + Log->Write("ERROR:\tRoot element does not exist"); + exit(EXIT_FAILURE); + } + + if( xRootNode->ValueStr () != "geometry" ) { + Log->Write("ERROR:\tRoot element value is not 'geometry'."); + exit(EXIT_FAILURE); + } + + if(string(xRootNode->Attribute("unit"))!="m") { + Log->Write("ERROR:\tOnly the unit m (metres) is supported. \n\tYou supplied [%s]",xRootNode->Attribute("unit")); + exit(EXIT_FAILURE); + } + + double version = xmltof(xRootNode->Attribute("version"), -1); + if (version != 0.5) { + Log->Write("ERROR: \tWrong goemetry version!"); + Log->Write("ERROR: \tOnly version >= %s supported",JPS_VERSION); + Log->Write("ERROR: \tPlease update the version of your geometry file to %s",JPS_VERSION); + exit(EXIT_FAILURE); + } + _caption = xmltoa(xRootNode->Attribute("caption"), "virtual building"); + + + //The file has two main nodes + //<rooms> and <transitions> + + + //processing the rooms node + TiXmlNode* xRoomsNode = xRootNode->FirstChild("rooms"); + if (!xRoomsNode) { + Log->Write("ERROR: \tThe geometry should have at least one room and one subroom"); + exit(EXIT_FAILURE); + } + + for(TiXmlElement* xRoom = xRoomsNode->FirstChildElement("room"); xRoom; + xRoom = xRoom->NextSiblingElement("room")) { + + Room* room = new Room(); + + string room_id = xmltoa(xRoom->Attribute("id"), "-1"); + room->SetID(xmltoi(room_id.c_str(), -1)); + + string caption = "room " + room_id; + room->SetCaption( + xmltoa(xRoom->Attribute("caption"), caption.c_str())); + + double position = xmltof(xRoom->Attribute("zpos"), 0.0); + + //TODO?? what the hell is that for ? + //if(position>6.0) position+=50; + room->SetZPos(position); + + //parsing the subrooms + //processing the rooms node + //TiXmlNode* xSubroomsNode = xRoom->FirstChild("subroom"); + + for(TiXmlElement* xSubRoom = xRoom->FirstChildElement("subroom"); xSubRoom; + xSubRoom = xSubRoom->NextSiblingElement("subroom")) { + + + string subroom_id = xmltoa(xSubRoom->Attribute("id"), "-1"); + string closed = xmltoa(xSubRoom->Attribute("closed"), "0"); + string type = xmltoa(xSubRoom->Attribute("class"),"subroom"); + + //get the equation of the plane if any + double A_x = xmltof(xSubRoom->Attribute("A_x"), 0.0); + double B_y = xmltof(xSubRoom->Attribute("B_y"), 0.0); + double C_z = xmltof(xSubRoom->Attribute("C_z"), 0.0); + + SubRoom* subroom = NULL; + + if (type == "stair") { + if(xSubRoom->FirstChildElement("up")==NULL) { + Log->Write("ERROR:\t the attribute <up> and <down> are missing for the stair"); + Log->Write("ERROR:\t check your geometry file"); + exit(EXIT_FAILURE); + } + double up_x = xmltof( xSubRoom->FirstChildElement("up")->Attribute("px"), 0.0); + double up_y = xmltof( xSubRoom->FirstChildElement("up")->Attribute("py"), 0.0); + double down_x = xmltof( xSubRoom->FirstChildElement("down")->Attribute("py"), 0.0); + double down_y = xmltof( xSubRoom->FirstChildElement("down")->Attribute("py"), 0.0); + subroom = new Stair(); + ((Stair*)subroom)->SetUp(Point(up_x,up_y)); + ((Stair*)subroom)->SetDown(Point(down_x,down_y)); + } else { + //normal subroom or corridor + subroom = new NormalSubRoom(); + } + + subroom->SetType(type); + subroom->SetPlanEquation(A_x,B_y,C_z); + subroom->SetRoomID(room->GetID()); + subroom->SetSubRoomID(xmltoi(subroom_id.c_str(), -1)); + + //looking for polygons (walls) + for(TiXmlElement* xPolyVertices = xSubRoom->FirstChildElement("polygon"); xPolyVertices; + xPolyVertices = xPolyVertices->NextSiblingElement("polygon")) { + + for (TiXmlElement* xVertex = xPolyVertices->FirstChildElement( + "vertex"); + xVertex && xVertex != xPolyVertices->LastChild("vertex"); + xVertex = xVertex->NextSiblingElement("vertex")) { + + double x1 = xmltof(xVertex->Attribute("px")); + double y1 = xmltof(xVertex->Attribute("py")); + double x2 = xmltof(xVertex->NextSiblingElement("vertex")->Attribute("px")); + double y2 = xmltof(xVertex->NextSiblingElement("vertex")->Attribute("py")); + + subroom->AddWall(Wall(Point(x1, y1), Point(x2, y2))); + } + + } + + //looking for obstacles + for(TiXmlElement* xObstacle = xSubRoom->FirstChildElement("obstacle"); xObstacle; + xObstacle = xObstacle->NextSiblingElement("obstacle")) { + + int id = xmltof(xObstacle->Attribute("id"), -1); + int height = xmltof(xObstacle->Attribute("height"), 0); + double closed = xmltof(xObstacle->Attribute("closed"), 0); + string caption = xmltoa(xObstacle->Attribute("caption"),"-1"); + + Obstacle* obstacle = new Obstacle(); + obstacle->SetId(id); + obstacle->SetCaption(caption); + obstacle->SetClosed(closed); + obstacle->SetHeight(height); + + //looking for polygons (walls) + for(TiXmlElement* xPolyVertices = xObstacle->FirstChildElement("polygon"); xPolyVertices; + xPolyVertices = xPolyVertices->NextSiblingElement("polygon")) { + + for (TiXmlElement* xVertex = xPolyVertices->FirstChildElement( + "vertex"); + xVertex && xVertex != xPolyVertices->LastChild("vertex"); + xVertex = xVertex->NextSiblingElement("vertex")) { + + double x1 = xmltof(xVertex->Attribute("px")); + double y1 = xmltof(xVertex->Attribute("py")); + double x2 = xmltof(xVertex->NextSiblingElement("vertex")->Attribute("px")); + double y2 = xmltof(xVertex->NextSiblingElement("vertex")->Attribute("py")); + obstacle->AddWall(Wall(Point(x1, y1), Point(x2, y2))); + } + } + subroom->AddObstacle(obstacle); + } + room->AddSubRoom(subroom); + } + + //parsing the crossings + TiXmlNode* xCrossingsNode = xRoom->FirstChild("crossings"); + if(xCrossingsNode) + for(TiXmlElement* xCrossing = xCrossingsNode->FirstChildElement("crossing"); xCrossing; + xCrossing = xCrossing->NextSiblingElement("crossing")) { + + int id = xmltoi(xCrossing->Attribute("id"), -1); + int sub1_id = xmltoi(xCrossing->Attribute("subroom1_id"), -1); + int sub2_id = xmltoi(xCrossing->Attribute("subroom2_id"), -1); + + double x1 = xmltof( xCrossing->FirstChildElement("vertex")->Attribute("px")); + double y1 = xmltof( xCrossing->FirstChildElement("vertex")->Attribute("py")); + double x2 = xmltof( xCrossing->LastChild("vertex")->ToElement()->Attribute("px")); + double y2 = xmltof( xCrossing->LastChild("vertex")->ToElement()->Attribute("py")); + + Crossing* c = new Crossing(); + c->SetID(id); + c->SetPoint1(Point(x1, y1)); + c->SetPoint2(Point(x2, y2)); + + c->SetSubRoom1(room->GetSubRoom(sub1_id)); + c->SetSubRoom2(room->GetSubRoom(sub2_id)); + c->SetRoom1(room); + AddCrossing(c); + + room->GetSubRoom(sub1_id)->AddCrossing(c); + room->GetSubRoom(sub2_id)->AddCrossing(c); + } + + AddRoom(room); + } + + + // all rooms are read, now proceed with transitions + TiXmlNode* xTransNode = xRootNode->FirstChild("transitions"); + if(xTransNode) + for(TiXmlElement* xTrans = xTransNode->FirstChildElement("transition"); xTrans; + xTrans = xTrans->NextSiblingElement("transition")) { + + int id = xmltoi(xTrans->Attribute("id"), -1); + string caption = "door " + id; + caption = xmltoa(xTrans->Attribute("caption"), caption.c_str()); + int room1_id = xmltoi(xTrans->Attribute("room1_id"), -1); + int room2_id = xmltoi(xTrans->Attribute("room2_id"), -1); + int subroom1_id = xmltoi(xTrans->Attribute("subroom1_id"), -1); + int subroom2_id = xmltoi(xTrans->Attribute("subroom2_id"), -1); + string type = xmltoa(xTrans->Attribute("type"), "normal"); + + double x1 = xmltof( xTrans->FirstChildElement("vertex")->Attribute("px")); + double y1 = xmltof( xTrans->FirstChildElement("vertex")->Attribute("py")); + + double x2 = xmltof( xTrans->LastChild("vertex")->ToElement()->Attribute("px")); + double y2 = xmltof( xTrans->LastChild("vertex")->ToElement()->Attribute("py")); + + + Transition* t = new Transition(); + t->SetID(id); + t->SetCaption(caption); + t->SetPoint1(Point(x1, y1)); + t->SetPoint2(Point(x2, y2)); + t->SetType(type); + + if (room1_id != -1 && subroom1_id != -1) { + //Room* room = _rooms[room1_id]; + Room* room = GetRoom(room1_id); + SubRoom* subroom = room->GetSubRoom(subroom1_id); + + //subroom->AddGoalID(t->GetUniqueID()); + //MPI + room->AddTransitionID(t->GetUniqueID()); + t->SetRoom1(room); + t->SetSubRoom1(subroom); + + //new implementation + subroom->AddTransition(t); + } + if (room2_id != -1 && subroom2_id != -1) { + Room* room = _rooms[room2_id]; + SubRoom* subroom = room->GetSubRoom(subroom2_id); + //subroom->AddGoalID(t->GetUniqueID()); + //MPI + room->AddTransitionID(t->GetUniqueID()); + t->SetRoom2(room); + t->SetSubRoom2(subroom); + + //new implementation + subroom->AddTransition(t); + } + + AddTransition(t); + } + + + Log->Write("INFO: \tLoading building file successful!!!\n"); } -void Building::WriteToErrorLog() const { - Log->Write("GEOMETRY: "); - for (int i = 0; i < GetNumberOfRooms(); i++) { - Room* r = GetRoom(i); - r->WriteToErrorLog(); - } - Log->Write("ROUTING: "); - - for (map<int, Crossing*>::const_iterator iter = _crossings.begin(); - iter != _crossings.end(); ++iter) { - iter->second->WriteToErrorLog(); - } - for (map<int, Transition*>::const_iterator iter = _transitions.begin(); - iter != _transitions.end(); ++iter) { - iter->second->WriteToErrorLog(); - } - for (map<int, Hline*>::const_iterator iter = _hLines.begin(); - iter != _hLines.end(); ++iter) { - iter->second->WriteToErrorLog(); - } - Log->Write("\n"); +void Building::WriteToErrorLog() const +{ + Log->Write("GEOMETRY: "); + for (int i = 0; i < GetNumberOfRooms(); i++) { + Room* r = GetRoom(i); + r->WriteToErrorLog(); + } + Log->Write("ROUTING: "); + + for (map<int, Crossing*>::const_iterator iter = _crossings.begin(); + iter != _crossings.end(); ++iter) { + iter->second->WriteToErrorLog(); + } + for (map<int, Transition*>::const_iterator iter = _transitions.begin(); + iter != _transitions.end(); ++iter) { + iter->second->WriteToErrorLog(); + } + for (map<int, Hline*>::const_iterator iter = _hLines.begin(); + iter != _hLines.end(); ++iter) { + iter->second->WriteToErrorLog(); + } + Log->Write("\n"); } -Room* Building::GetRoom(string caption) const { - for (unsigned int r = 0; r < _rooms.size(); r++) { - if (_rooms[r]->GetCaption() == caption) - return _rooms[r]; - } - Log->Write("Warning: Room not found with caption " + caption); - //return NULL; - exit(EXIT_FAILURE); +Room* Building::GetRoom(string caption) const +{ + for (unsigned int r = 0; r < _rooms.size(); r++) { + if (_rooms[r]->GetCaption() == caption) + return _rooms[r]; + } + Log->Write("Warning: Room not found with caption " + caption); + //return NULL; + exit(EXIT_FAILURE); } -void Building::AddCrossing(Crossing* line) { - if (_crossings.count(line->GetID()) != 0) { - char tmp[CLENGTH]; - sprintf(tmp, - "ERROR: Duplicate index for crossing found [%d] in Routing::AddCrossing()", - line->GetID()); - Log->Write(tmp); - exit(EXIT_FAILURE); - } - _crossings[line->GetID()] = line; +void Building::AddCrossing(Crossing* line) +{ + if (_crossings.count(line->GetID()) != 0) { + char tmp[CLENGTH]; + sprintf(tmp, + "ERROR: Duplicate index for crossing found [%d] in Routing::AddCrossing()", + line->GetID()); + Log->Write(tmp); + exit(EXIT_FAILURE); + } + _crossings[line->GetID()] = line; } -void Building::AddTransition(Transition* line) { - if (_transitions.count(line->GetID()) != 0) { - char tmp[CLENGTH]; - sprintf(tmp, - "ERROR: Duplicate index for transition found [%d] in Routing::AddTransition()", - line->GetID()); - Log->Write(tmp); - exit(EXIT_FAILURE); - } - _transitions[line->GetID()] = line; +void Building::AddTransition(Transition* line) +{ + if (_transitions.count(line->GetID()) != 0) { + char tmp[CLENGTH]; + sprintf(tmp, + "ERROR: Duplicate index for transition found [%d] in Routing::AddTransition()", + line->GetID()); + Log->Write(tmp); + exit(EXIT_FAILURE); + } + _transitions[line->GetID()] = line; } -void Building::AddHline(Hline* line) { - if (_hLines.count(line->GetID()) != 0) { - // check if the lines are identical - Hline* ori= _hLines[line->GetID()]; - if(ori->operator ==(*line)){ - Log->Write("INFO: Skipping identical hlines with ID [%d]",line->GetID()); - return; - } - else - { - Log->Write( - "ERROR: Duplicate index for hlines found [%d] in Routing::AddHline(). You have [%d] hlines", - line->GetID(), _hLines.size()); - exit(EXIT_FAILURE); - } - } - _hLines[line->GetID()] = line; +void Building::AddHline(Hline* line) +{ + if (_hLines.count(line->GetID()) != 0) { + // check if the lines are identical + Hline* ori= _hLines[line->GetID()]; + if(ori->operator ==(*line)) { + Log->Write("INFO: Skipping identical hlines with ID [%d]",line->GetID()); + return; + } else { + Log->Write( + "ERROR: Duplicate index for hlines found [%d] in Routing::AddHline(). You have [%d] hlines", + line->GetID(), _hLines.size()); + exit(EXIT_FAILURE); + } + } + _hLines[line->GetID()] = line; } -void Building::AddGoal(Goal* goal) { - if (_goals.count(goal->GetId()) != 0) { - Log->Write( - "ERROR: Duplicate index for goal found [%d] in Routing::AddGoal()", - goal->GetId()); - exit(EXIT_FAILURE); - } - _goals[goal->GetId()] = goal; +void Building::AddGoal(Goal* goal) +{ + if (_goals.count(goal->GetId()) != 0) { + Log->Write( + "ERROR: Duplicate index for goal found [%d] in Routing::AddGoal()", + goal->GetId()); + exit(EXIT_FAILURE); + } + _goals[goal->GetId()] = goal; } -const map<int, Crossing*>& Building::GetAllCrossings() const { - return _crossings; +const map<int, Crossing*>& Building::GetAllCrossings() const +{ + return _crossings; } -const map<int, Transition*>& Building::GetAllTransitions() const { - return _transitions; +const map<int, Transition*>& Building::GetAllTransitions() const +{ + return _transitions; } -const map<int, Hline*>& Building::GetAllHlines() const { - return _hLines; +const map<int, Hline*>& Building::GetAllHlines() const +{ + return _hLines; } -const map<int, Goal*>& Building::GetAllGoals() const { - return _goals; +const map<int, Goal*>& Building::GetAllGoals() const +{ + return _goals; } -Transition* Building::GetTransition(string caption) const { - //eventually - map<int, Transition*>::const_iterator itr; - for(itr = _transitions.begin(); itr != _transitions.end(); ++itr){ - if (itr->second->GetCaption() == caption) - return itr->second; - } - - Log->Write("WARNING: No Transition with Caption: " + caption); - exit(EXIT_FAILURE); +Transition* Building::GetTransition(string caption) const +{ + //eventually + map<int, Transition*>::const_iterator itr; + for(itr = _transitions.begin(); itr != _transitions.end(); ++itr) { + if (itr->second->GetCaption() == caption) + return itr->second; + } + + Log->Write("WARNING: No Transition with Caption: " + caption); + exit(EXIT_FAILURE); } -Transition* Building::GetTransition(int ID) { - if (_transitions.count(ID) == 1) { - return _transitions[ID]; - } else { - if (ID == -1) - return NULL; - else { - Log->Write( - "ERROR: I could not find any transition with the 'ID' [%d]. You have defined [%d] transitions", - ID, _transitions.size()); - exit(EXIT_FAILURE); - } - } +Transition* Building::GetTransition(int ID) +{ + if (_transitions.count(ID) == 1) { + return _transitions[ID]; + } else { + if (ID == -1) + return NULL; + else { + Log->Write( + "ERROR: I could not find any transition with the 'ID' [%d]. You have defined [%d] transitions", + ID, _transitions.size()); + exit(EXIT_FAILURE); + } + } } -Goal* Building::GetFinalGoal(int ID) { - if (_goals.count(ID) == 1) { - return _goals[ID]; - } else { - if (ID == -1) - return NULL; - else { - Log->Write( - "ERROR: I could not find any goal with the 'ID' [%d]. You have defined [%d] goals", - ID, _goals.size()); - exit(EXIT_FAILURE); - } - } +Goal* Building::GetFinalGoal(int ID) +{ + if (_goals.count(ID) == 1) { + return _goals[ID]; + } else { + if (ID == -1) + return NULL; + else { + Log->Write( + "ERROR: I could not find any goal with the 'ID' [%d]. You have defined [%d] goals", + ID, _goals.size()); + exit(EXIT_FAILURE); + } + } } -Crossing* Building::GetTransOrCrossByName(string caption) const { - - { - //eventually - map<int, Transition*>::const_iterator itr; - for(itr = _transitions.begin(); itr != _transitions.end(); ++itr){ - if (itr->second->GetCaption() == caption) - return itr->second; - } - } - { - //finally the crossings - map<int, Crossing*>::const_iterator itr; - for(itr = _crossings.begin(); itr != _crossings.end(); ++itr){ - if (itr->second->GetCaption() == caption) - return itr->second; - } - } - - Log->Write("WARNING: No Transition or Crossing with Caption: " + caption); - return NULL; +Crossing* Building::GetTransOrCrossByName(string caption) const +{ + + { + //eventually + map<int, Transition*>::const_iterator itr; + for(itr = _transitions.begin(); itr != _transitions.end(); ++itr) { + if (itr->second->GetCaption() == caption) + return itr->second; + } + } + { + //finally the crossings + map<int, Crossing*>::const_iterator itr; + for(itr = _crossings.begin(); itr != _crossings.end(); ++itr) { + if (itr->second->GetCaption() == caption) + return itr->second; + } + } + + Log->Write("WARNING: No Transition or Crossing with Caption: " + caption); + return NULL; } -Crossing* Building::GetTransOrCrossByUID(int id) const { - { - //eventually - map<int, Transition*>::const_iterator itr; - for(itr = _transitions.begin(); itr != _transitions.end(); ++itr){ - if (itr->second->GetUniqueID()== id) - return itr->second; - } - } - { - //finally the crossings - map<int, Crossing*>::const_iterator itr; - for(itr = _crossings.begin(); itr != _crossings.end(); ++itr){ - if (itr->second->GetUniqueID() == id) - return itr->second; - } - } - - Log->Write("WARNING: No Transition or Crossing with ID %d: " ,id); - return NULL; +Crossing* Building::GetTransOrCrossByUID(int id) const +{ + { + //eventually + map<int, Transition*>::const_iterator itr; + for(itr = _transitions.begin(); itr != _transitions.end(); ++itr) { + if (itr->second->GetUniqueID()== id) + return itr->second; + } + } + { + //finally the crossings + map<int, Crossing*>::const_iterator itr; + for(itr = _crossings.begin(); itr != _crossings.end(); ++itr) { + if (itr->second->GetUniqueID() == id) + return itr->second; + } + } + + Log->Write("WARNING: No Transition or Crossing with ID %d: " ,id); + return NULL; } -SubRoom* Building::GetSubRoomByUID( int uid){ - for (unsigned int i = 0; i < _rooms.size();i++) { - Room* room = _rooms[i]; - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - if (sub->GetUID()==uid) return sub;; - } - } - Log->Write("ERROR:\t No subroom exits with the unique id %d",uid); - return NULL; +SubRoom* Building::GetSubRoomByUID( int uid) +{ + for (unsigned int i = 0; i < _rooms.size(); i++) { + Room* room = _rooms[i]; + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + if (sub->GetUID()==uid) return sub;; + } + } + Log->Write("ERROR:\t No subroom exits with the unique id %d",uid); + return NULL; } -bool Building::IsVisible(Line* l1, Line* l2, bool considerHlines){ - for (unsigned int i = 0; i < _rooms.size();i++) { - Room* room = _rooms[i]; - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - if(sub->IsVisible(l1,l2,considerHlines)==false) return false; - } - } - return true; +bool Building::IsVisible(Line* l1, Line* l2, bool considerHlines) +{ + for (unsigned int i = 0; i < _rooms.size(); i++) { + Room* room = _rooms[i]; + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + if(sub->IsVisible(l1,l2,considerHlines)==false) return false; + } + } + return true; } -bool Building::IsVisible(const Point& p1, const Point& p2, bool considerHlines){ - for (unsigned int i = 0; i < _rooms.size();i++) { - Room* room = _rooms[i]; - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - if(sub->IsVisible(p1,p2,considerHlines)==false) return false; - } - } - return true; +bool Building::IsVisible(const Point& p1, const Point& p2, bool considerHlines) +{ + for (unsigned int i = 0; i < _rooms.size(); i++) { + Room* room = _rooms[i]; + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + if(sub->IsVisible(p1,p2,considerHlines)==false) return false; + } + } + return true; } -void Building::SanityCheck(){ - Log->Write("INFO: \tChecking the geometry for artifacts"); - for (unsigned int i = 0; i < _rooms.size();i++) { - Room* room = _rooms[i]; - - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - sub->SanityCheck(); - } - } - Log->Write("INFO: \t...Done!!!\n"); +void Building::SanityCheck() +{ + Log->Write("INFO: \tChecking the geometry for artifacts"); + for (unsigned int i = 0; i < _rooms.size(); i++) { + Room* room = _rooms[i]; + + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + sub->SanityCheck(); + } + } + Log->Write("INFO: \t...Done!!!\n"); } #ifdef _SIMULATOR //TODO: merge this with Update and improve runtime -void Building::UpdateVerySlow(){ - - vector<Pedestrian*> nonConformPeds; - for (int i = 0; i < GetNumberOfRooms(); i++) { - Room* room = GetRoom(i); - - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - for (int k = 0; k < sub->GetNumberOfPedestrians(); k++) { - Pedestrian* ped = sub->GetPedestrian(k); - //set the new room if needed - if ((ped->GetFinalDestination() == FINAL_DEST_OUT) - && (GetRoom(ped->GetRoomID())->GetCaption() == "outside")) { - - sub->DeletePedestrian(k--); - DeletePedestrian(ped); - } else if ((ped->GetFinalDestination() != FINAL_DEST_OUT) - && (_goals[ped->GetFinalDestination()]->Contains( - ped->GetPos()))) { - sub->DeletePedestrian(k--); - DeletePedestrian(ped); - } else if (!sub->IsInSubRoom(ped)) { - nonConformPeds.push_back(ped); - sub->DeletePedestrian(k--); - } - } - } - } - - // reset that pedestrians who left their room not via the intended exit - for (int p = 0; p < (int) nonConformPeds.size(); p++) { - Pedestrian* ped = nonConformPeds[p]; - bool assigned = false; - for (int i = 0; i < GetNumberOfRooms(); i++) { - Room* room = GetRoom(i); - //if(room->GetCaption()=="outside") continue; - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - SubRoom* old_sub= _rooms[ped->GetRoomID()]->GetSubRoom(ped->GetSubRoomID()); - if ((sub->IsInSubRoom(ped->GetPos())) && (sub->IsDirectlyConnectedWith(old_sub))) { - ped->SetRoomID(room->GetID(), room->GetCaption()); - ped->SetSubRoomID(sub->GetSubRoomID()); - ped->ClearMentalMap(); // reset the destination - //ped->FindRoute(); - sub->AddPedestrian(ped); - assigned = true; - break; - } - } - if (assigned == true) - break; // stop the loop - } - if (assigned == false) { - DeletePedestrian(ped); - } - } - - // find the new goals, the parallel way - - //FIXME temporary fix for the safest path router - if(dynamic_cast<SafestPathRouter*>(_routingEngine->GetRouter(1))) - { - - SafestPathRouter* spr = dynamic_cast<SafestPathRouter*>(_routingEngine->GetRouter(1)); - spr->ComputeAndUpdateDestinations(_allPedestians); - } - else - { - unsigned int nSize = _allPedestians.size(); - int nThreads = omp_get_max_threads(); - - // check if worth sharing the work - if (nSize < 12) - nThreads = 1; - - int partSize = nSize / nThreads; - - #pragma omp parallel default(shared) num_threads(nThreads) - { - const int threadID = omp_get_thread_num(); - int start = threadID * partSize; - int end = (threadID + 1) * partSize - 1; - if ((threadID == nThreads - 1)) - end = nSize - 1; - - for (int p = start; p <= end; ++p) { - if (_allPedestians[p]->FindRoute() == -1) { - //a destination could not be found for that pedestrian - //Log->Write("\tINFO: \tCould not found a route for pedestrian %d",_allPedestians[p]->GetID()); - //Log->Write("\tINFO: \tHe has reached the target cell"); - DeletePedFromSim(_allPedestians[p]); - //exit(EXIT_FAILURE); - } - } - } - } +void Building::UpdateVerySlow() +{ + + vector<Pedestrian*> nonConformPeds; + for (int i = 0; i < GetNumberOfRooms(); i++) { + Room* room = GetRoom(i); + + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + for (int k = 0; k < sub->GetNumberOfPedestrians(); k++) { + Pedestrian* ped = sub->GetPedestrian(k); + //set the new room if needed + if ((ped->GetFinalDestination() == FINAL_DEST_OUT) + && (GetRoom(ped->GetRoomID())->GetCaption() == "outside")) { + + sub->DeletePedestrian(k--); + DeletePedestrian(ped); + } else if ((ped->GetFinalDestination() != FINAL_DEST_OUT) + && (_goals[ped->GetFinalDestination()]->Contains( + ped->GetPos()))) { + sub->DeletePedestrian(k--); + DeletePedestrian(ped); + } else if (!sub->IsInSubRoom(ped)) { + nonConformPeds.push_back(ped); + sub->DeletePedestrian(k--); + } + } + } + } + + // reset that pedestrians who left their room not via the intended exit + for (int p = 0; p < (int) nonConformPeds.size(); p++) { + Pedestrian* ped = nonConformPeds[p]; + bool assigned = false; + for (int i = 0; i < GetNumberOfRooms(); i++) { + Room* room = GetRoom(i); + //if(room->GetCaption()=="outside") continue; + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + SubRoom* old_sub= _rooms[ped->GetRoomID()]->GetSubRoom(ped->GetSubRoomID()); + if ((sub->IsInSubRoom(ped->GetPos())) && (sub->IsDirectlyConnectedWith(old_sub))) { + ped->SetRoomID(room->GetID(), room->GetCaption()); + ped->SetSubRoomID(sub->GetSubRoomID()); + ped->ClearMentalMap(); // reset the destination + //ped->FindRoute(); + sub->AddPedestrian(ped); + assigned = true; + break; + } + } + if (assigned == true) + break; // stop the loop + } + if (assigned == false) { + DeletePedestrian(ped); + } + } + + // find the new goals, the parallel way + + //FIXME temporary fix for the safest path router + if(dynamic_cast<SafestPathRouter*>(_routingEngine->GetRouter(1))) { + + SafestPathRouter* spr = dynamic_cast<SafestPathRouter*>(_routingEngine->GetRouter(1)); + spr->ComputeAndUpdateDestinations(_allPedestians); + } else { + unsigned int nSize = _allPedestians.size(); + int nThreads = omp_get_max_threads(); + + // check if worth sharing the work + if (nSize < 12) + nThreads = 1; + + int partSize = nSize / nThreads; + + #pragma omp parallel default(shared) num_threads(nThreads) + { + const int threadID = omp_get_thread_num(); + int start = threadID * partSize; + int end = (threadID + 1) * partSize - 1; + if ((threadID == nThreads - 1)) + end = nSize - 1; + + for (int p = start; p <= end; ++p) { + if (_allPedestians[p]->FindRoute() == -1) { + //a destination could not be found for that pedestrian + //Log->Write("\tINFO: \tCould not found a route for pedestrian %d",_allPedestians[p]->GetID()); + //Log->Write("\tINFO: \tHe has reached the target cell"); + DeletePedFromSim(_allPedestians[p]); + //exit(EXIT_FAILURE); + } + } + } + } } -void Building::Update() { - // some peds may change the room via another crossing than the primary intended one - // in that case they are set in the wrong room. - vector<Pedestrian*> nonConformPeds; - for (int i = 0; i < GetNumberOfRooms(); i++) { - Room* room = GetRoom(i); - - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - for (int k = 0; k < sub->GetNumberOfPedestrians(); k++) { - Pedestrian* ped = sub->GetPedestrian(k); - //set the new room if needed - if (!sub->IsInSubRoom(ped)) { - // the peds has changed the room and is farther than 50 cm from - // the exit, thats a real problem. - if (ped->GetExitLine()->DistTo(ped->GetPos()) > 0.50) { - Log->Write( - "WARNING: Building::update() pedestrian [%d] left the room/subroom [%s][%d/%d] " - "via unknown exit[??%d] \n Position: (%f, %f), distance to exit: (%f)", - ped->GetID(), - _rooms[ped->GetRoomID()]->GetCaption().c_str(), - ped->GetRoomID(), ped->GetSubRoomID(), - ped->GetExitIndex(), ped->GetPos().GetX(), - ped->GetPos().GetY(),ped->GetExitLine()->DistTo(ped->GetPos())); - //ped->Dump(ped->GetPedIndex()); - //std::cout << ped->GetLastDestination() << " " - // << ped->GetNextDestination() << std::endl; - //exit(0); - nonConformPeds.push_back(ped); - sub->DeletePedestrian(k--); - continue; // next pedestrian - } - - //safely converting (upcasting) the NavLine to a crossing. - Crossing* cross = - dynamic_cast<Crossing*>(ped->GetExitLine()); - if (cross == NULL) { - Log->Write("ERROR: Building::update() type casting error for ped %d",ped->GetID()); - Log->Write("ERROR: Fix Me !"); - nonConformPeds.push_back(ped); - exit(EXIT_FAILURE); - continue; - //fixme all portal should be derived from crossings - } - - SubRoom* other_sub = cross->GetOtherSubRoom( - room->GetID(), j); - - if (other_sub) { - int nextSubRoom = other_sub->GetSubRoomID(); - int nextRoom = other_sub->GetRoomID(); - ped->SetSubRoomID(nextSubRoom); - ped->SetRoomID(nextRoom, - GetRoom(nextRoom)->GetCaption()); - other_sub->AddPedestrian(ped); - - } else { - DeletePedestrian(ped); - //continue; - } - // Lösche Fußgänger aus aktuellem SubRoom - sub->DeletePedestrian(k--); // k--; - } - // neues Ziel setzten - //pRouting->FindExit(ped); - } - } - } - - // reset that pedestrians who left their room not via the intended exit - for (int p = 0; p < (int) nonConformPeds.size(); p++) { - Pedestrian* ped = nonConformPeds[p]; - bool assigned = false; - for (int i = 0; i < GetNumberOfRooms(); i++) { - Room* room = GetRoom(i); - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - //only relocate in the same room - // or only in neighbouring rooms - if (room->GetID() != ped->GetRoomID()) - continue; - if (sub->IsInSubRoom(ped->GetPos())) { - //set in the new room - Log->Write("pedestrian %d relocated from room/subroom [%s] %d/%d to [%s] %d/%d ", - ped->GetID(), - GetRoom(ped->GetRoomID())->GetCaption().c_str(), - ped->GetRoomID(), ped->GetSubRoomID(), - room->GetCaption().c_str(), i, j); - ped->SetRoomID(room->GetID(), room->GetCaption()); - ped->SetSubRoomID(sub->GetSubRoomID()); - ped->ClearMentalMap(); // reset the destination - ped->FindRoute(); - sub->AddPedestrian(ped); - assigned = true; - break; - } - } - if (assigned == true) - break; // stop the loop - } - if (assigned == false) { - DeletePedestrian(ped); - } - } - - // find the new goals, the parallel way - - unsigned int nSize = _allPedestians.size(); - int nThreads = omp_get_max_threads(); - - // check if worth sharing the work - if (nSize < 12) - nThreads = 1; - - int partSize = nSize / nThreads; - -#pragma omp parallel default(shared) num_threads(nThreads) - { - const int threadID = omp_get_thread_num(); - int start = threadID * partSize; - int end = (threadID + 1) * partSize - 1; - if ((threadID == nThreads - 1)) - end = nSize - 1; - - for (int p = start; p <= end; ++p) { - if (_allPedestians[p]->FindRoute() == -1) { - //a destination could not be found for that pedestrian - //Log->Write("\tINFO: \tCould not found a route for pedestrian %d",_allPedestians[p]->GetID()); - //Log->Write("\tINFO: \tHe has reached the target cell"); - DeletePedFromSim(_allPedestians[p]); - exit(EXIT_FAILURE); - } - } - } - - //cleaning up - //CleanUpTheScene(); +void Building::Update() +{ + // some peds may change the room via another crossing than the primary intended one + // in that case they are set in the wrong room. + vector<Pedestrian*> nonConformPeds; + for (int i = 0; i < GetNumberOfRooms(); i++) { + Room* room = GetRoom(i); + + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + for (int k = 0; k < sub->GetNumberOfPedestrians(); k++) { + Pedestrian* ped = sub->GetPedestrian(k); + //set the new room if needed + if (!sub->IsInSubRoom(ped)) { + // the peds has changed the room and is farther than 50 cm from + // the exit, thats a real problem. + if (ped->GetExitLine()->DistTo(ped->GetPos()) > 0.50) { + Log->Write( + "WARNING: Building::update() pedestrian [%d] left the room/subroom [%s][%d/%d] " + "via unknown exit[??%d] \n Position: (%f, %f), distance to exit: (%f)", + ped->GetID(), + _rooms[ped->GetRoomID()]->GetCaption().c_str(), + ped->GetRoomID(), ped->GetSubRoomID(), + ped->GetExitIndex(), ped->GetPos().GetX(), + ped->GetPos().GetY(),ped->GetExitLine()->DistTo(ped->GetPos())); + //ped->Dump(ped->GetPedIndex()); + //std::cout << ped->GetLastDestination() << " " + // << ped->GetNextDestination() << std::endl; + //exit(0); + nonConformPeds.push_back(ped); + sub->DeletePedestrian(k--); + continue; // next pedestrian + } + + //safely converting (upcasting) the NavLine to a crossing. + Crossing* cross = + dynamic_cast<Crossing*>(ped->GetExitLine()); + if (cross == NULL) { + Log->Write("ERROR: Building::update() type casting error for ped %d",ped->GetID()); + Log->Write("ERROR: Fix Me !"); + nonConformPeds.push_back(ped); + exit(EXIT_FAILURE); + continue; + //fixme all portal should be derived from crossings + } + + SubRoom* other_sub = cross->GetOtherSubRoom( + room->GetID(), j); + + if (other_sub) { + int nextSubRoom = other_sub->GetSubRoomID(); + int nextRoom = other_sub->GetRoomID(); + ped->SetSubRoomID(nextSubRoom); + ped->SetRoomID(nextRoom, + GetRoom(nextRoom)->GetCaption()); + other_sub->AddPedestrian(ped); + + } else { + DeletePedestrian(ped); + //continue; + } + // Lösche Fußgänger aus aktuellem SubRoom + sub->DeletePedestrian(k--); // k--; + } + // neues Ziel setzten + //pRouting->FindExit(ped); + } + } + } + + // reset that pedestrians who left their room not via the intended exit + for (int p = 0; p < (int) nonConformPeds.size(); p++) { + Pedestrian* ped = nonConformPeds[p]; + bool assigned = false; + for (int i = 0; i < GetNumberOfRooms(); i++) { + Room* room = GetRoom(i); + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + //only relocate in the same room + // or only in neighbouring rooms + if (room->GetID() != ped->GetRoomID()) + continue; + if (sub->IsInSubRoom(ped->GetPos())) { + //set in the new room + Log->Write("pedestrian %d relocated from room/subroom [%s] %d/%d to [%s] %d/%d ", + ped->GetID(), + GetRoom(ped->GetRoomID())->GetCaption().c_str(), + ped->GetRoomID(), ped->GetSubRoomID(), + room->GetCaption().c_str(), i, j); + ped->SetRoomID(room->GetID(), room->GetCaption()); + ped->SetSubRoomID(sub->GetSubRoomID()); + ped->ClearMentalMap(); // reset the destination + ped->FindRoute(); + sub->AddPedestrian(ped); + assigned = true; + break; + } + } + if (assigned == true) + break; // stop the loop + } + if (assigned == false) { + DeletePedestrian(ped); + } + } + + // find the new goals, the parallel way + + unsigned int nSize = _allPedestians.size(); + int nThreads = omp_get_max_threads(); + + // check if worth sharing the work + if (nSize < 12) + nThreads = 1; + + int partSize = nSize / nThreads; + + #pragma omp parallel default(shared) num_threads(nThreads) + { + const int threadID = omp_get_thread_num(); + int start = threadID * partSize; + int end = (threadID + 1) * partSize - 1; + if ((threadID == nThreads - 1)) + end = nSize - 1; + + for (int p = start; p <= end; ++p) { + if (_allPedestians[p]->FindRoute() == -1) { + //a destination could not be found for that pedestrian + //Log->Write("\tINFO: \tCould not found a route for pedestrian %d",_allPedestians[p]->GetID()); + //Log->Write("\tINFO: \tHe has reached the target cell"); + DeletePedFromSim(_allPedestians[p]); + exit(EXIT_FAILURE); + } + } + } + + //cleaning up + //CleanUpTheScene(); } -void Building::InitPhiAllPeds(double pDt) { - for (int i = 0; i < GetNumberOfRooms(); i++) { - Room* room = GetRoom(i); - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - for (int k = 0; k < sub->GetNumberOfPedestrians(); k++) { - double cosPhi, sinPhi; - Pedestrian* ped = sub->GetPedestrian(k); - ped->Setdt(pDt); //set the simulation step - ped->SetRoomID(room->GetID(), room->GetCaption()); - //a destination could not be found for that pedestrian - if (ped->FindRoute() == -1) { - DeletePedFromSim(ped); - //sub->DeletePedestrian(k--); - continue; - } - Line* e = ped->GetExitLine(); - const Point& e1 = e->GetPoint1(); - const Point& e2 = e->GetPoint2(); - Point target = (e1 + e2) * 0.5; - Point d = target - ped->GetPos(); - double dist = d.Norm(); - if (dist != 0.0) { - cosPhi = d.GetX() / dist; - sinPhi = d.GetY() / dist; - } else { - Log->Write( - "ERROR: \tBuilding::InitPhiAllPeds() cannot initialise phi! " - "dist to target ist 0\n"); - exit(0); - } - - JEllipse E = ped->GetEllipse(); - E.SetCosPhi(cosPhi); - E.SetSinPhi(sinPhi); - ped->SetEllipse(E); - } - } - } +void Building::InitPhiAllPeds(double pDt) +{ + for (int i = 0; i < GetNumberOfRooms(); i++) { + Room* room = GetRoom(i); + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + for (int k = 0; k < sub->GetNumberOfPedestrians(); k++) { + double cosPhi, sinPhi; + Pedestrian* ped = sub->GetPedestrian(k); + ped->Setdt(pDt); //set the simulation step + ped->SetRoomID(room->GetID(), room->GetCaption()); + //a destination could not be found for that pedestrian + if (ped->FindRoute() == -1) { + DeletePedFromSim(ped); + //sub->DeletePedestrian(k--); + continue; + } + Line* e = ped->GetExitLine(); + const Point& e1 = e->GetPoint1(); + const Point& e2 = e->GetPoint2(); + Point target = (e1 + e2) * 0.5; + Point d = target - ped->GetPos(); + double dist = d.Norm(); + if (dist != 0.0) { + cosPhi = d.GetX() / dist; + sinPhi = d.GetY() / dist; + } else { + Log->Write( + "ERROR: \tBuilding::InitPhiAllPeds() cannot initialise phi! " + "dist to target ist 0\n"); + exit(0); + } + + JEllipse E = ped->GetEllipse(); + E.SetCosPhi(cosPhi); + E.SetSinPhi(sinPhi); + ped->SetEllipse(E); + } + } + } } -void Building::UpdateGrid() { - _linkedCellGrid->Update(_allPedestians); +void Building::UpdateGrid() +{ + _linkedCellGrid->Update(_allPedestians); } -void Building::InitGrid(double cellSize) { - - // first look for the geometry boundaries - double x_min = FLT_MAX; - double x_max = FLT_MIN; - double y_min = FLT_MAX; - double y_max = FLT_MIN; - - //finding the bounding of the grid - // and collect the pedestrians - for (unsigned int r = 0; r < _rooms.size(); r++) { - Room* room = _rooms[r]; - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - const vector<Wall>& allWalls = sub->GetAllWalls(); - - for (unsigned int a = 0; a < allWalls.size(); a++) { - double x1 = allWalls[a].GetPoint1().GetX(); - double y1 = allWalls[a].GetPoint1().GetY(); - double x2 = allWalls[a].GetPoint2().GetX(); - double y2 = allWalls[a].GetPoint2().GetY(); - - double xmax = (x1 > x2) ? x1 : x2; - double xmin = (x1 > x2) ? x2 : x1; - double ymax = (y1 > y2) ? y1 : y2; - double ymin = (y1 > y2) ? y2 : y1; - - 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; - } - } - } - - for (unsigned int wa = 0; wa < _rooms.size(); wa++) { - Room* room = _rooms[wa]; - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - for (int k = 0; k < sub->GetNumberOfPedestrians(); k++) { - Pedestrian* ped = sub->GetPedestrian(k); - _allPedestians.push_back(ped); - } - } - } - - //make the grid slightly larger. - x_min = x_min - 1.0; - x_max = x_max + 1.0; - y_min = y_min - 1.0; - y_max = y_max + 1.0; - - double boundaries[] = { x_min, x_max, y_min, y_max }; - int pedsCount = _allPedestians.size(); - - //no algorithms - // the domain is made of a sigle cell - if(cellSize==-1){ - Log->Write("INFO: \tBrute Force will be used for neighborhoods query"); - if ( (x_max-x_min) < (y_max-y_min) ){ - cellSize=(y_max-y_min); - }else { - cellSize=(x_max-x_min); - } - - }else{ - Log->Write("INFO: \tInitializing the grid with cell size: %f ", cellSize); - } - - _linkedCellGrid = new LCGrid(boundaries, cellSize, pedsCount); - _linkedCellGrid->ShallowCopy(_allPedestians); - - Log->Write("INFO: \tDone with Initializing the grid "); +void Building::InitGrid(double cellSize) +{ + + // first look for the geometry boundaries + double x_min = FLT_MAX; + double x_max = FLT_MIN; + double y_min = FLT_MAX; + double y_max = FLT_MIN; + + //finding the bounding of the grid + // and collect the pedestrians + for (unsigned int r = 0; r < _rooms.size(); r++) { + Room* room = _rooms[r]; + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + const vector<Wall>& allWalls = sub->GetAllWalls(); + + for (unsigned int a = 0; a < allWalls.size(); a++) { + double x1 = allWalls[a].GetPoint1().GetX(); + double y1 = allWalls[a].GetPoint1().GetY(); + double x2 = allWalls[a].GetPoint2().GetX(); + double y2 = allWalls[a].GetPoint2().GetY(); + + double xmax = (x1 > x2) ? x1 : x2; + double xmin = (x1 > x2) ? x2 : x1; + double ymax = (y1 > y2) ? y1 : y2; + double ymin = (y1 > y2) ? y2 : y1; + + 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; + } + } + } + + for (unsigned int wa = 0; wa < _rooms.size(); wa++) { + Room* room = _rooms[wa]; + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + for (int k = 0; k < sub->GetNumberOfPedestrians(); k++) { + Pedestrian* ped = sub->GetPedestrian(k); + _allPedestians.push_back(ped); + } + } + } + + //make the grid slightly larger. + x_min = x_min - 1.0; + x_max = x_max + 1.0; + y_min = y_min - 1.0; + y_max = y_max + 1.0; + + double boundaries[] = { x_min, x_max, y_min, y_max }; + int pedsCount = _allPedestians.size(); + + //no algorithms + // the domain is made of a sigle cell + if(cellSize==-1) { + Log->Write("INFO: \tBrute Force will be used for neighborhoods query"); + if ( (x_max-x_min) < (y_max-y_min) ) { + cellSize=(y_max-y_min); + } else { + cellSize=(x_max-x_min); + } + + } else { + Log->Write("INFO: \tInitializing the grid with cell size: %f ", cellSize); + } + + _linkedCellGrid = new LCGrid(boundaries, cellSize, pedsCount); + _linkedCellGrid->ShallowCopy(_allPedestians); + + Log->Write("INFO: \tDone with Initializing the grid "); } -void Building::DumpSubRoomInRoom(int roomID, int subID) { - SubRoom* sub = GetRoom(roomID)->GetSubRoom(subID); - if (sub->GetNumberOfPedestrians() == 0) - return; - cout << "dumping room/subroom " << roomID << " / " << subID << endl; - for (int p = 0; p < sub->GetNumberOfPedestrians(); p++) { - Pedestrian* ped = sub->GetPedestrian(p); - cout << " ID: " << ped->GetID(); - cout << " Index: " << p << endl; - } +void Building::DumpSubRoomInRoom(int roomID, int subID) +{ + SubRoom* sub = GetRoom(roomID)->GetSubRoom(subID); + if (sub->GetNumberOfPedestrians() == 0) + return; + cout << "dumping room/subroom " << roomID << " / " << subID << endl; + for (int p = 0; p < sub->GetNumberOfPedestrians(); p++) { + Pedestrian* ped = sub->GetPedestrian(p); + cout << " ID: " << ped->GetID(); + cout << " Index: " << p << endl; + } } -void Building::LoadRoutingInfo(const string &filename) { - - - Log->Write("INFO:\tLoading extra routing information"); - if (filename == "") { - Log->Write("INFO:\t No file supplied !"); - Log->Write("INFO:\t done with loading extra routing information"); - return; - } - TiXmlDocument docRouting(filename); - if (!docRouting.LoadFile()){ - Log->Write("ERROR: \t%s", docRouting.ErrorDesc()); - Log->Write("ERROR: \t could not parse the routing file"); - exit(EXIT_FAILURE); - } - - TiXmlElement* xRootNode = docRouting.RootElement(); - if( ! xRootNode ) { - Log->Write("ERROR:\tRoot element does not exist"); - exit(EXIT_FAILURE); - } - - //load goals and routes - TiXmlNode* xGoalsNode = xRootNode->FirstChild("routing")->FirstChild("goals"); - - - if(xGoalsNode) - for(TiXmlElement* e = xGoalsNode->FirstChildElement("goal"); e; - e = e->NextSiblingElement("goal")) { - - int id = xmltof(e->Attribute("id"), -1); - int isFinal= string(e->Attribute("final"))=="true"?true:false; - string caption = xmltoa(e->Attribute("caption"),"-1"); - - Goal* goal = new Goal(); - goal->SetId(id); - goal->SetCaption(caption); - goal->SetIsFinalGoal(isFinal); - - //looking for polygons (walls) - for(TiXmlElement* xPolyVertices = e->FirstChildElement("polygon"); xPolyVertices; - xPolyVertices = xPolyVertices->NextSiblingElement("polygon")) { - - for (TiXmlElement* xVertex = xPolyVertices->FirstChildElement( - "vertex"); - xVertex && xVertex != xPolyVertices->LastChild("vertex"); - xVertex = xVertex->NextSiblingElement("vertex")) { - - double x1 = xmltof(xVertex->Attribute("px")); - double y1 = xmltof(xVertex->Attribute("py")); - double x2 = xmltof(xVertex->NextSiblingElement("vertex")->Attribute("px")); - double y2 = xmltof(xVertex->NextSiblingElement("vertex")->Attribute("py")); - goal->AddWall(Wall(Point(x1, y1), Point(x2, y2))); - } - } - - goal->ConvertLineToPoly(); - AddGoal(goal); - _routingEngine->AddFinalDestinationID(goal->GetId()); - } - - //load routes - TiXmlNode* xTripsNode = xRootNode->FirstChild("routing")->FirstChild("routes"); - - if(xTripsNode) - for(TiXmlElement* trip = xTripsNode->FirstChildElement("route"); trip; - trip = trip->NextSiblingElement("route")) { - - double id = xmltof(trip->Attribute("id"), -1); - if (id == -1) { - Log->Write("ERROR:\t id missing for trip"); - exit(EXIT_FAILURE); - } - string sTrip = trip->FirstChild()->ValueStr(); - vector<string> vTrip; - vTrip.clear(); - - char* str = (char*) sTrip.c_str(); - char *p = strtok(str, ":"); - while (p) { - vTrip.push_back(xmltoa(p)); - p = strtok(NULL, ":"); - } - _routingEngine->AddTrip(vTrip); - } - Log->Write("INFO:\tdone with loading extra routing information"); +void Building::LoadRoutingInfo(const string &filename) +{ + + + Log->Write("INFO:\tLoading extra routing information"); + if (filename == "") { + Log->Write("INFO:\t No file supplied !"); + Log->Write("INFO:\t done with loading extra routing information"); + return; + } + TiXmlDocument docRouting(filename); + if (!docRouting.LoadFile()) { + Log->Write("ERROR: \t%s", docRouting.ErrorDesc()); + Log->Write("ERROR: \t could not parse the routing file"); + exit(EXIT_FAILURE); + } + + TiXmlElement* xRootNode = docRouting.RootElement(); + if( ! xRootNode ) { + Log->Write("ERROR:\tRoot element does not exist"); + exit(EXIT_FAILURE); + } + + //load goals and routes + TiXmlNode* xGoalsNode = xRootNode->FirstChild("routing")->FirstChild("goals"); + + + if(xGoalsNode) + for(TiXmlElement* e = xGoalsNode->FirstChildElement("goal"); e; + e = e->NextSiblingElement("goal")) { + + int id = xmltof(e->Attribute("id"), -1); + int isFinal= string(e->Attribute("final"))=="true"?true:false; + string caption = xmltoa(e->Attribute("caption"),"-1"); + + Goal* goal = new Goal(); + goal->SetId(id); + goal->SetCaption(caption); + goal->SetIsFinalGoal(isFinal); + + //looking for polygons (walls) + for(TiXmlElement* xPolyVertices = e->FirstChildElement("polygon"); xPolyVertices; + xPolyVertices = xPolyVertices->NextSiblingElement("polygon")) { + + for (TiXmlElement* xVertex = xPolyVertices->FirstChildElement( + "vertex"); + xVertex && xVertex != xPolyVertices->LastChild("vertex"); + xVertex = xVertex->NextSiblingElement("vertex")) { + + double x1 = xmltof(xVertex->Attribute("px")); + double y1 = xmltof(xVertex->Attribute("py")); + double x2 = xmltof(xVertex->NextSiblingElement("vertex")->Attribute("px")); + double y2 = xmltof(xVertex->NextSiblingElement("vertex")->Attribute("py")); + goal->AddWall(Wall(Point(x1, y1), Point(x2, y2))); + } + } + + goal->ConvertLineToPoly(); + AddGoal(goal); + _routingEngine->AddFinalDestinationID(goal->GetId()); + } + + //load routes + TiXmlNode* xTripsNode = xRootNode->FirstChild("routing")->FirstChild("routes"); + + if(xTripsNode) + for(TiXmlElement* trip = xTripsNode->FirstChildElement("route"); trip; + trip = trip->NextSiblingElement("route")) { + + double id = xmltof(trip->Attribute("id"), -1); + if (id == -1) { + Log->Write("ERROR:\t id missing for trip"); + exit(EXIT_FAILURE); + } + string sTrip = trip->FirstChild()->ValueStr(); + vector<string> vTrip; + vTrip.clear(); + + char* str = (char*) sTrip.c_str(); + char *p = strtok(str, ":"); + while (p) { + vTrip.push_back(xmltoa(p)); + p = strtok(NULL, ":"); + } + _routingEngine->AddTrip(vTrip); + } + Log->Write("INFO:\tdone with loading extra routing information"); } -void Building::LoadTrafficInfo() { - - Log->Write("INFO:\tLoading the traffic info file"); - - string trafficFile=""; - TiXmlDocument doc(_projectFilename); - if (!doc.LoadFile()){ - Log->Write("ERROR: \t%s", doc.ErrorDesc()); - Log->Write("ERROR: \t could not parse the project file"); - exit(EXIT_FAILURE); - } - - TiXmlNode* xRootNode = doc.RootElement()->FirstChild("traffic_constraints"); - if( ! xRootNode ) { - Log->Write("WARNING:\tcould not find any traffic information"); - return; - //exit(EXIT_FAILURE); - } - - //processing the rooms node - TiXmlNode* xRoomsNode = xRootNode->FirstChild("rooms"); - if(xRoomsNode) - for(TiXmlElement* xRoom = xRoomsNode->FirstChildElement("room"); xRoom; - xRoom = xRoom->NextSiblingElement("room")) { - - double id = xmltof(xRoom->Attribute("room_id"), -1); - string state = xmltoa(xRoom->Attribute("state"), "good"); - RoomState status = (state == "good") ? ROOM_CLEAN : ROOM_SMOKED; - GetRoom(id)->SetState(status); - } - - //processing the doors node - TiXmlNode* xDoorsNode = xRootNode->FirstChild("doors"); - if(xDoorsNode) - for(TiXmlElement* xDoor = xDoorsNode->FirstChildElement("door"); xDoor; - xDoor = xDoor->NextSiblingElement("door")) { - - int id = xmltoi(xDoor->Attribute("trans_id"), -1); - string state = xmltoa(xDoor->Attribute("state"), "open"); - - //store transition in a map and call getTransition/getCrossin - if (state == "open") { - GetTransition(id)->Open(); - } else if (state == "close") { - GetTransition(id)->Close(); - } else { - Log->Write("WARNING:\t Unknown door state: %s", state.c_str()); - } - } - Log->Write("INFO:\tDone with loading traffic info file"); +void Building::LoadTrafficInfo() +{ + + Log->Write("INFO:\tLoading the traffic info file"); + + string trafficFile=""; + TiXmlDocument doc(_projectFilename); + if (!doc.LoadFile()) { + Log->Write("ERROR: \t%s", doc.ErrorDesc()); + Log->Write("ERROR: \t could not parse the project file"); + exit(EXIT_FAILURE); + } + + TiXmlNode* xRootNode = doc.RootElement()->FirstChild("traffic_constraints"); + if( ! xRootNode ) { + Log->Write("WARNING:\tcould not find any traffic information"); + return; + //exit(EXIT_FAILURE); + } + + //processing the rooms node + TiXmlNode* xRoomsNode = xRootNode->FirstChild("rooms"); + if(xRoomsNode) + for(TiXmlElement* xRoom = xRoomsNode->FirstChildElement("room"); xRoom; + xRoom = xRoom->NextSiblingElement("room")) { + + double id = xmltof(xRoom->Attribute("room_id"), -1); + string state = xmltoa(xRoom->Attribute("state"), "good"); + RoomState status = (state == "good") ? ROOM_CLEAN : ROOM_SMOKED; + GetRoom(id)->SetState(status); + } + + //processing the doors node + TiXmlNode* xDoorsNode = xRootNode->FirstChild("doors"); + if(xDoorsNode) + for(TiXmlElement* xDoor = xDoorsNode->FirstChildElement("door"); xDoor; + xDoor = xDoor->NextSiblingElement("door")) { + + int id = xmltoi(xDoor->Attribute("trans_id"), -1); + string state = xmltoa(xDoor->Attribute("state"), "open"); + + //store transition in a map and call getTransition/getCrossin + if (state == "open") { + GetTransition(id)->Open(); + } else if (state == "close") { + GetTransition(id)->Close(); + } else { + Log->Write("WARNING:\t Unknown door state: %s", state.c_str()); + } + } + Log->Write("INFO:\tDone with loading traffic info file"); } -void Building::DeletePedestrian(Pedestrian* ped) { - vector<Pedestrian*>::iterator it; - it = find(_allPedestians.begin(), _allPedestians.end(), ped); - if (it == _allPedestians.end()) { - Log->Write ("\tINFO: \tPed not found with ID %d ",ped->GetID()); - //FIXME: the pedestrians should always exists. check this in connection with the mesh router. - return; - } else { - //save the path history for this pedestrian before removing from the simulation - if (_savePathway) { - string results; - string path = (*it)->GetPath(); - vector<string> brokenpaths; - StringExplode(path, ">", &brokenpaths); - for (unsigned int i = 0; i < brokenpaths.size(); i++) { - vector<string> tags; - StringExplode(brokenpaths[i], ":", &tags); - string room = _rooms[atoi(tags[0].c_str())]->GetCaption(); - string trans =GetTransition(atoi(tags[1].c_str()))->GetCaption(); - //ignore crossings/hlines - if (trans != "") - _pathWayStream << room << " " << trans << endl; - } - - } - cout << "rescued agent: " << (*it)->GetID() << endl; - _allPedestians.erase(it); - } - //update the stats before deleting - Transition* trans =GetTransitionByUID(ped->GetExitIndex()); - if(trans) { - trans->IncreaseDoorUsage(1, ped->GetGlobalTime()); - } - delete ped; +void Building::DeletePedestrian(Pedestrian* ped) +{ + vector<Pedestrian*>::iterator it; + it = find(_allPedestians.begin(), _allPedestians.end(), ped); + if (it == _allPedestians.end()) { + Log->Write ("\tINFO: \tPed not found with ID %d ",ped->GetID()); + //FIXME: the pedestrians should always exists. check this in connection with the mesh router. + return; + } else { + //save the path history for this pedestrian before removing from the simulation + if (_savePathway) { + string results; + string path = (*it)->GetPath(); + vector<string> brokenpaths; + StringExplode(path, ">", &brokenpaths); + for (unsigned int i = 0; i < brokenpaths.size(); i++) { + vector<string> tags; + StringExplode(brokenpaths[i], ":", &tags); + string room = _rooms[atoi(tags[0].c_str())]->GetCaption(); + string trans =GetTransition(atoi(tags[1].c_str()))->GetCaption(); + //ignore crossings/hlines + if (trans != "") + _pathWayStream << room << " " << trans << endl; + } + + } + cout << "rescued agent: " << (*it)->GetID() << endl; + _allPedestians.erase(it); + } + //update the stats before deleting + Transition* trans =GetTransitionByUID(ped->GetExitIndex()); + if(trans) { + trans->IncreaseDoorUsage(1, ped->GetGlobalTime()); + } + delete ped; } -void Building::DeletePedFromSim(Pedestrian* ped) { - SubRoom* sub = _rooms[ped->GetRoomID()]->GetSubRoom(ped->GetSubRoomID()); - for (int p = 0; p < sub->GetNumberOfPedestrians(); p++) { - if (sub->GetPedestrian(p)->GetID() == ped->GetID()) { - sub->DeletePedestrian(p); - DeletePedestrian(ped); - return; - } - } +void Building::DeletePedFromSim(Pedestrian* ped) +{ + SubRoom* sub = _rooms[ped->GetRoomID()]->GetSubRoom(ped->GetSubRoomID()); + for (int p = 0; p < sub->GetNumberOfPedestrians(); p++) { + if (sub->GetPedestrian(p)->GetID() == ped->GetID()) { + sub->DeletePedestrian(p); + DeletePedestrian(ped); + return; + } + } } -const vector<Pedestrian*>& Building::GetAllPedestrians() const { - return _allPedestians; +const vector<Pedestrian*>& Building::GetAllPedestrians() const +{ + return _allPedestians; } -void Building::AddPedestrian(Pedestrian* ped) { - - // for(unsigned int p = 0;p<pAllPedestians.size();p++){ - // Pedestrian* ped1=pAllPedestians[p]; - // if(ped->GetPedIndex()==ped1->GetPedIndex()){ - // cout<<"Pedestrian already in the room ??? "<<ped->GetPedIndex()<<endl; - // return; - // } - // } - _allPedestians.push_back(ped); +void Building::AddPedestrian(Pedestrian* ped) +{ + + // for(unsigned int p = 0;p<pAllPedestians.size();p++){ + // Pedestrian* ped1=pAllPedestians[p]; + // if(ped->GetPedIndex()==ped1->GetPedIndex()){ + // cout<<"Pedestrian already in the room ??? "<<ped->GetPedIndex()<<endl; + // return; + // } + // } + _allPedestians.push_back(ped); } //obsolete -void Building::InitSavePedPathway(const string &filename) { - _pathWayStream.open(filename.c_str()); - _savePathway = true; - - if (_pathWayStream.is_open()) { - Log->Write("#INFO:\tsaving pedestrian paths to [ " + filename + " ]"); - _pathWayStream << "##pedestrian ways" << endl; - _pathWayStream << "#nomenclature roomid caption" << endl; - // for (unsigned int r=0;r< pRooms.size();r++){ - // Room* room= GetRoom(r); - // const vector<int>& goals=room->GetAllTransitionsIDs(); - // - // for(unsigned int g=0;g<goals.size();g++){ - // int exitid=goals[g]; - // string exit_caption=pRouting->GetGoal(exitid)->GetCaption(); - // PpathWayStream<<exitid<<" "<<exit_caption<<endl; - // } - // } - // - _pathWayStream << "#data room exit_id" << endl; - } else { - Log->Write("#INFO:\t Unable to open [ " + filename + " ]"); - Log->Write("#INFO:\t saving to stdout"); - - } +void Building::InitSavePedPathway(const string &filename) +{ + _pathWayStream.open(filename.c_str()); + _savePathway = true; + + if (_pathWayStream.is_open()) { + Log->Write("#INFO:\tsaving pedestrian paths to [ " + filename + " ]"); + _pathWayStream << "##pedestrian ways" << endl; + _pathWayStream << "#nomenclature roomid caption" << endl; + // for (unsigned int r=0;r< pRooms.size();r++){ + // Room* room= GetRoom(r); + // const vector<int>& goals=room->GetAllTransitionsIDs(); + // + // for(unsigned int g=0;g<goals.size();g++){ + // int exitid=goals[g]; + // string exit_caption=pRouting->GetGoal(exitid)->GetCaption(); + // PpathWayStream<<exitid<<" "<<exit_caption<<endl; + // } + // } + // + _pathWayStream << "#data room exit_id" << endl; + } else { + Log->Write("#INFO:\t Unable to open [ " + filename + " ]"); + Log->Write("#INFO:\t saving to stdout"); + + } } -void Building::CleanUpTheScene() { - //return; - static int counter = 0; - counter++; - static int totalSliced = 0; - - int updateRate = 80.0 / 0.01; // 20 seconds/pDt - - if (counter % updateRate == 0) { - for (unsigned int i = 0; i < _allPedestians.size(); i++) { - Pedestrian* ped = _allPedestians[i]; - - if (ped->GetDistanceSinceLastRecord() < 0.1) { - //delete from the simulation - DeletePedFromSim(ped); - - totalSliced++; - char msg[CLENGTH]; - sprintf(msg, "INFO:\t slicing Ped %d from room %s, total [%d]", - ped->GetID(), - _rooms[ped->GetRoomID()]->GetCaption().c_str(), - totalSliced); - Log->Write(msg); - } else { - ped->RecordActualPosition(); - } - - } - } +void Building::CleanUpTheScene() +{ + //return; + static int counter = 0; + counter++; + static int totalSliced = 0; + + int updateRate = 80.0 / 0.01; // 20 seconds/pDt + + if (counter % updateRate == 0) { + for (unsigned int i = 0; i < _allPedestians.size(); i++) { + Pedestrian* ped = _allPedestians[i]; + + if (ped->GetDistanceSinceLastRecord() < 0.1) { + //delete from the simulation + DeletePedFromSim(ped); + + totalSliced++; + char msg[CLENGTH]; + sprintf(msg, "INFO:\t slicing Ped %d from room %s, total [%d]", + ped->GetID(), + _rooms[ped->GetRoomID()]->GetCaption().c_str(), + totalSliced); + Log->Write(msg); + } else { + ped->RecordActualPosition(); + } + + } + } } void Building::StringExplode(string str, string separator, - vector<string>* results) { - size_t found; - found = str.find_first_of(separator); - while (found != string::npos) { - if (found > 0) { - results->push_back(str.substr(0, found)); - } - str = str.substr(found + 1); - found = str.find_first_of(separator); - } - if (str.length() > 0) { - results->push_back(str); - } + vector<string>* results) +{ + size_t found; + found = str.find_first_of(separator); + while (found != string::npos) { + if (found > 0) { + results->push_back(str.substr(0, found)); + } + str = str.substr(found + 1); + found = str.find_first_of(separator); + } + if (str.length() > 0) { + results->push_back(str); + } } -Pedestrian* Building::GetPedestrian(int pedID) const { - for (unsigned int i = 0; i < _rooms.size(); i++) { - Room* room = _rooms[i]; - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - for (int k = 0; k < sub->GetNumberOfPedestrians(); k++) { - Pedestrian* p = sub->GetPedestrian(k); - if (p->GetID() == pedID) { - return p; - } - } - } - } - return NULL; +Pedestrian* Building::GetPedestrian(int pedID) const +{ + for (unsigned int i = 0; i < _rooms.size(); i++) { + Room* room = _rooms[i]; + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + for (int k = 0; k < sub->GetNumberOfPedestrians(); k++) { + Pedestrian* p = sub->GetPedestrian(k); + if (p->GetID() == pedID) { + return p; + } + } + } + } + return NULL; } -int Building::GetNumberOfPedestrians() const { - int sum = 0; - for (unsigned int wa = 0; wa < _rooms.size(); wa++) { - sum += _rooms[wa]->GetNumberOfPedestrians(); - } - return sum; +int Building::GetNumberOfPedestrians() const +{ + int sum = 0; + for (unsigned int wa = 0; wa < _rooms.size(); wa++) { + sum += _rooms[wa]->GetNumberOfPedestrians(); + } + return sum; } -Transition* Building::GetTransitionByUID(int uid) const { - //eventually - map<int, Transition*>::const_iterator itr; - for(itr = _transitions.begin(); itr != _transitions.end(); ++itr){ - if (itr->second->GetUniqueID()== uid) - return itr->second; - } - return NULL; +Transition* Building::GetTransitionByUID(int uid) const +{ + //eventually + map<int, Transition*>::const_iterator itr; + for(itr = _transitions.begin(); itr != _transitions.end(); ++itr) { + if (itr->second->GetUniqueID()== uid) + return itr->second; + } + return NULL; } diff --git a/geometry/Building.h b/geometry/Building.h index b34af34b49d7fa7428489522176dff2bb6ab509b..47310402fc709fc223311fa23b0b9668288b879c 100644 --- a/geometry/Building.h +++ b/geometry/Building.h @@ -49,162 +49,162 @@ class LCGrid; class Building { - private: - std::string _caption; - std::string _projectFilename; - std::string _projectRootDir; - std::string _geometryFilename; - RoutingEngine* _routingEngine; - LCGrid* _linkedCellGrid; - std::vector<Room*> _rooms; - std::vector<Pedestrian*> _allPedestians; - - std::map<int, Crossing*> _crossings; - std::map<int, Transition*> _transitions; - std::map<int, Hline*> _hLines; - std::map<int, Goal*>_goals; - - /// pedestrians pathway - bool _savePathway; - std::ofstream _pathWayStream; - - public: - /// constructor - Building(); - /// destructor - virtual ~Building(); - - - void SetCaption(const std::string& s); - void SetRoutingEngine(RoutingEngine* r); - void SetRoom(Room* room, int index); - /// delete the ped from the ped vector - void DeletePedestrian(Pedestrian* ped); - /// delete the ped from the simulation - void DeletePedFromSim(Pedestrian* ped); - void AddPedestrian(Pedestrian* ped); - - - std::string GetCaption() const; - RoutingEngine* GetRoutingEngine() const; - const std::vector<Room*>& GetAllRooms() const; - const std::vector<Pedestrian*>& GetAllPedestrians() const; - Pedestrian* GetPedestrian( int pedID) const; - int GetNumberOfRooms() const; - int GetNumberOfGoals()const; - Room* GetRoom(int index) const; - Room* GetRoom(std::string caption)const; - - //TODO: implement the same methods for Crossings and Hlines - Transition* GetTransition(std::string caption) const; - Transition* GetTransition(int id) ; - - /** - * Not implemented - */ - Crossing* GetCrossing(int id); - - /** - * Not implemented - */ - Hline* GetHline(int id); - - - /** - * return the subroom with the corresponding unique identifier - * @param uid ,the unique identifier - * @return NULL if no exists with that identifier. - */ - SubRoom* GetSubRoomByUID( int uid); - - /** - * @return true if the two segments are visible from each other. - * Alls walls and transitions and crossings are used in this check. - * The use of hlines is optional, because they are not real, can can be considered transparent - */ - bool IsVisible(Line* l1, Line* l2, bool considerHlines=false); - - /** - * @return true if the two points are visible from each other. - * Alls walls and transitions and crossings are used in this check. - * The use of hlines is optional, because they are not real, can be considered transparent - */ - bool IsVisible(const Point& p1, const Point& p2, bool considerHlines=false); - - - /** - * @return a crossing or a transition matching the given caption. - * Return NULL if none is found - */ - Crossing* GetTransOrCrossByName(std::string caption) const; - - - /** - * @return a crossing or a transition matching the given uid. - * Return NULL if none is found - */ - Crossing* GetTransOrCrossByUID(int uid) const; - - - /** - * @return the transition matching the uid - */ - Transition* GetTransitionByUID(int uid) const; - - //TOD0: rename later to GetGoal - Goal* GetFinalGoal(int id); - - int GetNumberOfPedestrians() const; - - /** - * @return the linked-cell grid used for spatial query - */ - LCGrid* GetGrid() const; - - // convenience methods - void InitGeometry(); - void InitGrid(double cellSize); - //void InitRoomsAndSubroomsMap(); - void InitPhiAllPeds(double pDt); // initialize the direction of the ellipses - void InitSavePedPathway(const std::string &filename); - void AddRoom(Room* room); - void Update(); - void UpdateVerySlow(); - void UpdateGrid(); - void AddSurroundingRoom(); // add a final room (outside or world), that encompasses the complete geometry - void DumpSubRoomInRoom(int roomID, int subID); - - const std::map<int, Crossing*>& GetAllCrossings() const; - const std::map<int, Transition*>& GetAllTransitions() const; - const std::map<int, Hline*>& GetAllHlines() const; - const std::map<int, Goal*>& GetAllGoals() const; - - void AddCrossing(Crossing* line); - void AddTransition(Transition* line); - void AddHline(Hline* line); - void AddGoal(Goal* goal); - - const std::string& GetProjectRootDir() const; - const std::string& GetProjectFilename() const; - const std::string& GetGeometryFilename() const; - void SetProjectFilename(const std::string &filename) ; - void SetProjectRootDir(const std::string &filename); - void LoadBuildingFromFile(); - void LoadTrafficInfo(); - void LoadRoutingInfo(const std::string &filename); - void WriteToErrorLog() const; - - void CleanUpTheScene(); - - /** - * Check the scenario for possible errors and - * output user specific informations. - */ - void SanityCheck(); - - - private: - void StringExplode(std::string str, std::string separator, std::vector<std::string>* results); +private: + std::string _caption; + std::string _projectFilename; + std::string _projectRootDir; + std::string _geometryFilename; + RoutingEngine* _routingEngine; + LCGrid* _linkedCellGrid; + std::vector<Room*> _rooms; + std::vector<Pedestrian*> _allPedestians; + + std::map<int, Crossing*> _crossings; + std::map<int, Transition*> _transitions; + std::map<int, Hline*> _hLines; + std::map<int, Goal*>_goals; + + /// pedestrians pathway + bool _savePathway; + std::ofstream _pathWayStream; + +public: + /// constructor + Building(); + /// destructor + virtual ~Building(); + + + void SetCaption(const std::string& s); + void SetRoutingEngine(RoutingEngine* r); + void SetRoom(Room* room, int index); + /// delete the ped from the ped vector + void DeletePedestrian(Pedestrian* ped); + /// delete the ped from the simulation + void DeletePedFromSim(Pedestrian* ped); + void AddPedestrian(Pedestrian* ped); + + + std::string GetCaption() const; + RoutingEngine* GetRoutingEngine() const; + const std::vector<Room*>& GetAllRooms() const; + const std::vector<Pedestrian*>& GetAllPedestrians() const; + Pedestrian* GetPedestrian( int pedID) const; + int GetNumberOfRooms() const; + int GetNumberOfGoals()const; + Room* GetRoom(int index) const; + Room* GetRoom(std::string caption)const; + + //TODO: implement the same methods for Crossings and Hlines + Transition* GetTransition(std::string caption) const; + Transition* GetTransition(int id) ; + + /** + * Not implemented + */ + Crossing* GetCrossing(int id); + + /** + * Not implemented + */ + Hline* GetHline(int id); + + + /** + * return the subroom with the corresponding unique identifier + * @param uid ,the unique identifier + * @return NULL if no exists with that identifier. + */ + SubRoom* GetSubRoomByUID( int uid); + + /** + * @return true if the two segments are visible from each other. + * Alls walls and transitions and crossings are used in this check. + * The use of hlines is optional, because they are not real, can can be considered transparent + */ + bool IsVisible(Line* l1, Line* l2, bool considerHlines=false); + + /** + * @return true if the two points are visible from each other. + * Alls walls and transitions and crossings are used in this check. + * The use of hlines is optional, because they are not real, can be considered transparent + */ + bool IsVisible(const Point& p1, const Point& p2, bool considerHlines=false); + + + /** + * @return a crossing or a transition matching the given caption. + * Return NULL if none is found + */ + Crossing* GetTransOrCrossByName(std::string caption) const; + + + /** + * @return a crossing or a transition matching the given uid. + * Return NULL if none is found + */ + Crossing* GetTransOrCrossByUID(int uid) const; + + + /** + * @return the transition matching the uid + */ + Transition* GetTransitionByUID(int uid) const; + + //TOD0: rename later to GetGoal + Goal* GetFinalGoal(int id); + + int GetNumberOfPedestrians() const; + + /** + * @return the linked-cell grid used for spatial query + */ + LCGrid* GetGrid() const; + + // convenience methods + void InitGeometry(); + void InitGrid(double cellSize); + //void InitRoomsAndSubroomsMap(); + void InitPhiAllPeds(double pDt); // initialize the direction of the ellipses + void InitSavePedPathway(const std::string &filename); + void AddRoom(Room* room); + void Update(); + void UpdateVerySlow(); + void UpdateGrid(); + void AddSurroundingRoom(); // add a final room (outside or world), that encompasses the complete geometry + void DumpSubRoomInRoom(int roomID, int subID); + + const std::map<int, Crossing*>& GetAllCrossings() const; + const std::map<int, Transition*>& GetAllTransitions() const; + const std::map<int, Hline*>& GetAllHlines() const; + const std::map<int, Goal*>& GetAllGoals() const; + + void AddCrossing(Crossing* line); + void AddTransition(Transition* line); + void AddHline(Hline* line); + void AddGoal(Goal* goal); + + const std::string& GetProjectRootDir() const; + const std::string& GetProjectFilename() const; + const std::string& GetGeometryFilename() const; + void SetProjectFilename(const std::string &filename) ; + void SetProjectRootDir(const std::string &filename); + void LoadBuildingFromFile(); + void LoadTrafficInfo(); + void LoadRoutingInfo(const std::string &filename); + void WriteToErrorLog() const; + + void CleanUpTheScene(); + + /** + * Check the scenario for possible errors and + * output user specific informations. + */ + void SanityCheck(); + + +private: + void StringExplode(std::string str, std::string separator, std::vector<std::string>* results); }; diff --git a/geometry/Crossing.cpp b/geometry/Crossing.cpp index 2e5584494ec8a9a23610246dbc35b7a9249d9d1d..541bcba3194cba5d18941ca841988efa13417e4e 100644 --- a/geometry/Crossing.cpp +++ b/geometry/Crossing.cpp @@ -35,141 +35,161 @@ using namespace std; -Crossing::Crossing(){ - _id = -1; - _room1 = NULL; - _subRoom1 = NULL; - _subRoom2 = NULL; - _caption = ""; +Crossing::Crossing() +{ + _id = -1; + _room1 = NULL; + _subRoom1 = NULL; + _subRoom2 = NULL; + _caption = ""; } -Crossing::~Crossing() { +Crossing::~Crossing() +{ } -void Crossing::SetID(int ID) { - _id = ID; +void Crossing::SetID(int ID) +{ + _id = ID; } -void Crossing::SetRoom1(Room* r) { - _room1 = r; +void Crossing::SetRoom1(Room* r) +{ + _room1 = r; } -void Crossing::SetSubRoom1(SubRoom* r1) { - _subRoom1 = r1; +void Crossing::SetSubRoom1(SubRoom* r1) +{ + _subRoom1 = r1; } -void Crossing::SetSubRoom2(SubRoom* r2) { - _subRoom2 = r2; +void Crossing::SetSubRoom2(SubRoom* r2) +{ + _subRoom2 = r2; } -void Crossing::SetCaption(string s) { - _caption = s; +void Crossing::SetCaption(string s) +{ + _caption = s; } // Getter-Funktionen -int Crossing::GetID() const { - return _id; +int Crossing::GetID() const +{ + return _id; } -string Crossing::GetCaption() const { - return _caption; +string Crossing::GetCaption() const +{ + return _caption; } -Room* Crossing::GetRoom1() const { - return _room1; +Room* Crossing::GetRoom1() const +{ + return _room1; } -SubRoom* Crossing::GetSubRoom1() const { - return _subRoom1; +SubRoom* Crossing::GetSubRoom1() const +{ + return _subRoom1; } -SubRoom* Crossing::GetSubRoom2() const { - return _subRoom2; +SubRoom* Crossing::GetSubRoom2() const +{ + return _subRoom2; } // Sonstiges -bool Crossing::IsExit() const { - return false; +bool Crossing::IsExit() const +{ + return false; } -bool Crossing::IsOpen() const { - return true; +bool Crossing::IsOpen() const +{ + return true; } -bool Crossing::IsTransition() const { - return false; +bool Crossing::IsTransition() const +{ + return false; } -bool Crossing::IsInRoom(int roomID) const { - return _room1->GetID() == roomID; +bool Crossing::IsInRoom(int roomID) const +{ + return _room1->GetID() == roomID; } -bool Crossing::IsInSubRoom(int subroomID) const { - bool r1, r2; - if (_subRoom1 != NULL) - r1 = _subRoom1->GetSubRoomID() == subroomID; - else - r1 = false; - if (_subRoom2 != NULL) - r2 = _subRoom2->GetSubRoomID() == subroomID; - else - r2 = false; - return (r1 || r2); +bool Crossing::IsInSubRoom(int subroomID) const +{ + bool r1, r2; + if (_subRoom1 != NULL) + r1 = _subRoom1->GetSubRoomID() == subroomID; + else + r1 = false; + if (_subRoom2 != NULL) + r2 = _subRoom2->GetSubRoomID() == subroomID; + else + r2 = false; + return (r1 || r2); } /* gibt den ANDEREN Subroom != subroomID zurück * roomID wird hier nicht benötigt, aber in Transition::GetOtherSubRoom() * (virtuelle Funktion) */ -SubRoom* Crossing::GetOtherSubRoom(int roomID, int subroomID) const { - if (_subRoom1->GetSubRoomID() == subroomID) - return _subRoom2; - else if (_subRoom2->GetSubRoomID() == subroomID) - return _subRoom1; - else { - Log->Write("WARMING: \tCrossing::GetOtherSubRoom No exit found " - "on the other side\n ID=%hd, roomID=%hd, subroomID=%hd\n",GetID(),roomID,subroomID); - return NULL; - } +SubRoom* Crossing::GetOtherSubRoom(int roomID, int subroomID) const +{ + if (_subRoom1->GetSubRoomID() == subroomID) + return _subRoom2; + else if (_subRoom2->GetSubRoomID() == subroomID) + return _subRoom1; + else { + Log->Write("WARMING: \tCrossing::GetOtherSubRoom No exit found " + "on the other side\n ID=%hd, roomID=%hd, subroomID=%hd\n",GetID(),roomID,subroomID); + return NULL; + } } // Ausgabe -void Crossing::WriteToErrorLog() const { - string s; - char tmp[CLENGTH]; - sprintf(tmp, "\t\tCROSS: %d (%f, %f) -- (%f, %f)\n", GetID(), GetPoint1().GetX(), - GetPoint1().GetY(), GetPoint2().GetX(), GetPoint2().GetY()); - s.append(tmp); - sprintf(tmp, "\t\t\t\tSubRoom: %d <-> SubRoom: %d\n", GetSubRoom1()->GetSubRoomID(), - GetSubRoom2()->GetSubRoomID()); - s.append(tmp); - Log->Write(s); +void Crossing::WriteToErrorLog() const +{ + string s; + char tmp[CLENGTH]; + sprintf(tmp, "\t\tCROSS: %d (%f, %f) -- (%f, %f)\n", GetID(), GetPoint1().GetX(), + GetPoint1().GetY(), GetPoint2().GetX(), GetPoint2().GetY()); + s.append(tmp); + sprintf(tmp, "\t\t\t\tSubRoom: %d <-> SubRoom: %d\n", GetSubRoom1()->GetSubRoomID(), + GetSubRoom2()->GetSubRoomID()); + s.append(tmp); + Log->Write(s); } // TraVisTo Ausgabe -string Crossing::WriteElement() const { - //return ""; - string geometry; - char tmp[CLENGTH] = ""; - sprintf(tmp,"\t\t<door ID=\"%d\" color = \"250\" caption=\"%d_%d\">\n",GetUniqueID(),GetID(),GetUniqueID()); - geometry.append(tmp); - //geometry.append("\t\t<door color=\"250\">\n"); - sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\" />\n", - (GetPoint1().GetX()) * FAKTOR, - (GetPoint1().GetY()) * FAKTOR, - _subRoom1->GetElevation(GetPoint1())*FAKTOR); - geometry.append(tmp); - sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\" />\n", - (GetPoint2().GetX()) * FAKTOR, - (GetPoint2().GetY()) * FAKTOR, - _subRoom1->GetElevation(GetPoint2())*FAKTOR); - geometry.append(tmp); - geometry.append("\t\t</door>\n"); - return geometry; +string Crossing::WriteElement() const +{ + //return ""; + string geometry; + char tmp[CLENGTH] = ""; + sprintf(tmp,"\t\t<door ID=\"%d\" color = \"250\" caption=\"%d_%d\">\n",GetUniqueID(),GetID(),GetUniqueID()); + geometry.append(tmp); + //geometry.append("\t\t<door color=\"250\">\n"); + sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\" />\n", + (GetPoint1().GetX()) * FAKTOR, + (GetPoint1().GetY()) * FAKTOR, + _subRoom1->GetElevation(GetPoint1())*FAKTOR); + geometry.append(tmp); + sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\" />\n", + (GetPoint2().GetX()) * FAKTOR, + (GetPoint2().GetY()) * FAKTOR, + _subRoom1->GetElevation(GetPoint2())*FAKTOR); + geometry.append(tmp); + geometry.append("\t\t</door>\n"); + return geometry; } diff --git a/geometry/Crossing.h b/geometry/Crossing.h index 91f664c112f175f955c919b1d6f2d4f4857f08c8..b5a7d67415e909632da558b6ee120f14a058d277 100644 --- a/geometry/Crossing.h +++ b/geometry/Crossing.h @@ -36,111 +36,111 @@ class Room; class SubRoom; class Crossing : public NavLine { - private: - /// ? unique between crossings and transitions ? - int _id; - /// only one room needed, since a crossing only separates 2 subrooms - Room* _room1; - std::string _caption; - SubRoom* _subRoom1; - SubRoom* _subRoom2; - - public: - Crossing(); - virtual ~Crossing(); - - /** - * Set/Get the Id of the crossing - */ - void SetID(int ID); - - /** - * Set/Get the Id of the crossing - */ - int GetID () const; - - /** - * Set/Get the first room - */ - void SetRoom1(Room* r); - - /** - * Set/Get the crossing caption - */ - void SetCaption(std::string s); - - /** - * Set/Get the first subroom - */ - void SetSubRoom1(SubRoom* r1); - - /** - * Set/Get the second subroom - */ - void SetSubRoom2(SubRoom* r2); - - /** - * Set/Get the crossing caption - */ - std::string GetCaption() const; - - /** - * Set/Get the first room - */ - Room* GetRoom1() const; - - /** - * Set/Get the first subroom - */ - SubRoom* GetSubRoom1() const; - - /** - * Set/Get the second subroom - */ - SubRoom* GetSubRoom2() const; - - /** - * \return true if the subroomID is associated with the current crossing - */ - bool IsInSubRoom(int subroomID) const; - - - /** - * @return true if the crossing is open = passable - */ - virtual bool IsOpen() const; - - /** - * @return true if the crossing is an exit/transition. (Transitions are derived from this class) - * @see Transition - */ - virtual bool IsExit() const; - - /** - * - * @return true if it is a transition - */ - virtual bool IsTransition() const; - - /** - * @return true if the crossing/transintion/hline is associated with the room - */ - virtual bool IsInRoom(int roomID) const; - - /** - * @return the other subroom not matching the data - */ - virtual SubRoom* GetOtherSubRoom(int roomID, int subroomID) const; - - /** - * Debug output - */ - virtual void WriteToErrorLog() const; - - /** - * @return a nicely formatted string representation of the object - */ - virtual std::string WriteElement() const; +private: + /// ? unique between crossings and transitions ? + int _id; + /// only one room needed, since a crossing only separates 2 subrooms + Room* _room1; + std::string _caption; + SubRoom* _subRoom1; + SubRoom* _subRoom2; + +public: + Crossing(); + virtual ~Crossing(); + + /** + * Set/Get the Id of the crossing + */ + void SetID(int ID); + + /** + * Set/Get the Id of the crossing + */ + int GetID () const; + + /** + * Set/Get the first room + */ + void SetRoom1(Room* r); + + /** + * Set/Get the crossing caption + */ + void SetCaption(std::string s); + + /** + * Set/Get the first subroom + */ + void SetSubRoom1(SubRoom* r1); + + /** + * Set/Get the second subroom + */ + void SetSubRoom2(SubRoom* r2); + + /** + * Set/Get the crossing caption + */ + std::string GetCaption() const; + + /** + * Set/Get the first room + */ + Room* GetRoom1() const; + + /** + * Set/Get the first subroom + */ + SubRoom* GetSubRoom1() const; + + /** + * Set/Get the second subroom + */ + SubRoom* GetSubRoom2() const; + + /** + * \return true if the subroomID is associated with the current crossing + */ + bool IsInSubRoom(int subroomID) const; + + + /** + * @return true if the crossing is open = passable + */ + virtual bool IsOpen() const; + + /** + * @return true if the crossing is an exit/transition. (Transitions are derived from this class) + * @see Transition + */ + virtual bool IsExit() const; + + /** + * + * @return true if it is a transition + */ + virtual bool IsTransition() const; + + /** + * @return true if the crossing/transintion/hline is associated with the room + */ + virtual bool IsInRoom(int roomID) const; + + /** + * @return the other subroom not matching the data + */ + virtual SubRoom* GetOtherSubRoom(int roomID, int subroomID) const; + + /** + * Debug output + */ + virtual void WriteToErrorLog() const; + + /** + * @return a nicely formatted string representation of the object + */ + virtual std::string WriteElement() const; }; #endif /* _CROSSING_H */ diff --git a/geometry/Goal.cpp b/geometry/Goal.cpp index 1deff14d7a9ef39c89e875e1a534436d26d6e5ec..683cbef4e564b7b142d28528650b62e55dbbfd06 100644 --- a/geometry/Goal.cpp +++ b/geometry/Goal.cpp @@ -34,224 +34,241 @@ using namespace std; -Goal::Goal() { - _id=-1; - _caption="Goal"; - _isFinalGoal=0; - _walls = vector<Wall > (); - _poly = vector<Point > (); +Goal::Goal() +{ + _id=-1; + _caption="Goal"; + _isFinalGoal=0; + _walls = vector<Wall > (); + _poly = vector<Point > (); } -Goal::~Goal() { +Goal::~Goal() +{ } -void Goal::AddWall(const Wall& w) { - _walls.push_back(w); +void Goal::AddWall(const Wall& w) +{ + _walls.push_back(w); } -string Goal::GetCaption() const { - return _caption; +string Goal::GetCaption() const +{ + return _caption; } -void Goal::SetCaption(string caption) { - _caption = caption; +void Goal::SetCaption(string caption) +{ + _caption = caption; } -int Goal::GetId() const { - return _id; +int Goal::GetId() const +{ + return _id; } -void Goal::SetId(int id) { - _id = id; +void Goal::SetId(int id) +{ + _id = id; } -const vector<Point>& Goal::GetPolygon() const { - return _poly; +const vector<Point>& Goal::GetPolygon() const +{ + return _poly; } -string Goal::Write() { - string s; - Point pos; - - 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()); - - // add some fancy stuffs - if(_poly.size()>=4){ - s.append(Wall(_poly[0],_poly[2]).Write()); - s.append(Wall(_poly[1],_poly[3]).Write()); - } - //add the Goal 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()); - s.append(tmp); - - return s; +string Goal::Write() +{ + string s; + Point pos; + + 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()); + + // add some fancy stuffs + if(_poly.size()>=4) { + s.append(Wall(_poly[0],_poly[2]).Write()); + s.append(Wall(_poly[1],_poly[3]).Write()); + } + //add the Goal 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()); + s.append(tmp); + + return s; } -const vector<Wall>& Goal::GetAllWalls() const { - return _walls; +const vector<Wall>& Goal::GetAllWalls() const +{ + return _walls; } -int Goal::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); +int Goal::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); } -int Goal::GetIsFinalGoal() const { - return _isFinalGoal; +int Goal::GetIsFinalGoal() const +{ + return _isFinalGoal; } -void Goal::SetIsFinalGoal(int isFinalGoal) { - _isFinalGoal = isFinalGoal; +void Goal::SetIsFinalGoal(int isFinalGoal) +{ + _isFinalGoal = isFinalGoal; } // x-Koordinate der Linie von einer Eccke zur nächsten -double Goal::Xintercept(const Point& point1, const Point& point2, double hitY) const { - return (point2.GetX() - (((point2.GetY() - hitY) * (point1.GetX() - point2.GetX())) / - (point1.GetY() - point2.GetY()))); +double Goal::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 Goal::Contains(const Point& ped) const { - - - 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 Goal::Contains(const Point& ped) const +{ + + + 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; } -void Goal::ConvertLineToPoly() { - - vector<Line*> copy; - vector<Point> tmpPoly; - Point point; - Line* line; - // Alle Linienelemente in copy speichern - for (unsigned int i = 0; i < _walls.size(); i++) { - copy.push_back(&_walls[i]); - } - - 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: \tGoal::ConvertLineToPoly(): ID %d !!!\n", _id); - Log->Write(tmp); - exit(0); - } - _poly = tmpPoly; - - ComputeControid(); +void Goal::ConvertLineToPoly() +{ + + vector<Line*> copy; + vector<Point> tmpPoly; + Point point; + Line* line; + // Alle Linienelemente in copy speichern + for (unsigned int i = 0; i < _walls.size(); i++) { + copy.push_back(&_walls[i]); + } + + 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: \tGoal::ConvertLineToPoly(): ID %d !!!\n", _id); + Log->Write(tmp); + exit(0); + } + _poly = tmpPoly; + + ComputeControid(); } -const Point& Goal::GetCentroid() const { - return _centroid; +const Point& Goal::GetCentroid() const +{ + return _centroid; } -void Goal::ComputeControid() { - - 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); - - _centroid._x=px; - _centroid._y=py; +void Goal::ComputeControid() +{ + + 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); + + _centroid._x=px; + _centroid._y=py; } diff --git a/geometry/Goal.h b/geometry/Goal.h index 609a489819e790c142c9c84f4928cf12b30f1c53..e9e1370c905cb246ffc7f08d2a4de758d3a56fcd 100644 --- a/geometry/Goal.h +++ b/geometry/Goal.h @@ -37,96 +37,96 @@ class Wall; class Goal { - private: - int _isFinalGoal; - int _id; - Point _centroid; - std::string _caption; - std::vector<Wall> _walls; - std::vector<Point> _poly; - - public: - Goal(); - virtual ~Goal(); - - /** - * Set/Get the obstacles' caption - */ - std::string GetCaption() const; - - /** - * Set/Get the obstacles' caption - */ - void SetCaption(std::string caption); - - /** - * Set/Get the id of the Goal - */ - int GetId() const; - - /** - * Set/Get the id of the Goal - */ - void SetId(int id); - - /** - * construct the Goal by adding more walls - */ - void AddWall(const Wall& w); - - /** - * @return All walls that constitute the Goal - */ - const std::vector<Wall>& GetAllWalls() const; - - /** - * @return true if the point p is contained within the Closed Goal - */ - bool Contains(const Point& p) const; - - /** - * Create the obstacles polygonal structure from the walls - */ - void ConvertLineToPoly(); - - /** - * @return the Goal as a polygon - */ - const std::vector<Point>& GetPolygon() const; - - /** - * agents are remove from the simulation when they reached a final goal - */ - int GetIsFinalGoal() const; - - /** - * agents are remove from the simulation when they reached a final goal - */ - void SetIsFinalGoal(int isFinalGoal); - - /** - * @return the centroid of the subroom - * @see http://en.wikipedia.org/wiki/Centroid - */ - void ComputeControid() ; - - /** - * @return the centroid of the goal - * @see ComputeControid - */ - const Point& GetCentroid() const; - - /** - * @return a nicely formatted string representation of the Goal - */ - std::string Write(); - - private: - int WhichQuad(const Point& vertex, const Point& hitPos) const; - - // x-Koordinate der Linie von einer Eccke zur nächsten - double Xintercept(const Point& point1, const Point& point2, - double hitY) const; +private: + int _isFinalGoal; + int _id; + Point _centroid; + std::string _caption; + std::vector<Wall> _walls; + std::vector<Point> _poly; + +public: + Goal(); + virtual ~Goal(); + + /** + * Set/Get the obstacles' caption + */ + std::string GetCaption() const; + + /** + * Set/Get the obstacles' caption + */ + void SetCaption(std::string caption); + + /** + * Set/Get the id of the Goal + */ + int GetId() const; + + /** + * Set/Get the id of the Goal + */ + void SetId(int id); + + /** + * construct the Goal by adding more walls + */ + void AddWall(const Wall& w); + + /** + * @return All walls that constitute the Goal + */ + const std::vector<Wall>& GetAllWalls() const; + + /** + * @return true if the point p is contained within the Closed Goal + */ + bool Contains(const Point& p) const; + + /** + * Create the obstacles polygonal structure from the walls + */ + void ConvertLineToPoly(); + + /** + * @return the Goal as a polygon + */ + const std::vector<Point>& GetPolygon() const; + + /** + * agents are remove from the simulation when they reached a final goal + */ + int GetIsFinalGoal() const; + + /** + * agents are remove from the simulation when they reached a final goal + */ + void SetIsFinalGoal(int isFinalGoal); + + /** + * @return the centroid of the subroom + * @see http://en.wikipedia.org/wiki/Centroid + */ + void ComputeControid() ; + + /** + * @return the centroid of the goal + * @see ComputeControid + */ + const Point& GetCentroid() const; + + /** + * @return a nicely formatted string representation of the Goal + */ + std::string Write(); + +private: + int WhichQuad(const Point& vertex, const Point& hitPos) const; + + // x-Koordinate der Linie von einer Eccke zur nächsten + double Xintercept(const Point& point1, const Point& point2, + double hitY) const; }; diff --git a/geometry/Hline.cpp b/geometry/Hline.cpp index f215eb2f72e0796c668748bf5cec5abc98f3134b..ae87b8a6682443e838b8617acf23e9f6013f108f 100644 --- a/geometry/Hline.cpp +++ b/geometry/Hline.cpp @@ -30,87 +30,101 @@ using namespace std; -Hline::Hline() { - _room=NULL; - _subRoom=NULL; - _id=-1; +Hline::Hline() +{ + _room=NULL; + _subRoom=NULL; + _id=-1; } -Hline::~Hline() { +Hline::~Hline() +{ } -void Hline::SetID(int ID) { - _id=ID; +void Hline::SetID(int ID) +{ + _id=ID; } -void Hline::SetRoom(Room* r) { - _room=r; +void Hline::SetRoom(Room* r) +{ + _room=r; } -void Hline::SetCaption(string s) { - _caption=s; +void Hline::SetCaption(string s) +{ + _caption=s; } -void Hline::SetSubRoom(SubRoom* s) { - _subRoom=s; +void Hline::SetSubRoom(SubRoom* s) +{ + _subRoom=s; } -int Hline::GetID() const { - return _id; +int Hline::GetID() const +{ + return _id; } -string Hline::GetCaption() const { - return _caption; +string Hline::GetCaption() const +{ + return _caption; } -Room* Hline::GetRoom() const { - return _room; +Room* Hline::GetRoom() const +{ + return _room; } -SubRoom* Hline::GetSubRoom() const { - return _subRoom; +SubRoom* Hline::GetSubRoom() const +{ + return _subRoom; } -bool Hline::IsInSubRoom(int subroomID) const { - return _subRoom->GetSubRoomID() == subroomID; +bool Hline::IsInSubRoom(int subroomID) const +{ + return _subRoom->GetSubRoomID() == subroomID; } -bool Hline::IsInRoom(int roomID) const { - return _room->GetID() == roomID; +bool Hline::IsInRoom(int roomID) const +{ + return _room->GetID() == roomID; } -void Hline::WriteToErrorLog() const { - string s; - char tmp[CLENGTH]; - sprintf(tmp, "\t\tHline: %d (%f, %f) -- (%f, %f)\n", GetID(), GetPoint1().GetX(), - GetPoint1().GetY(), GetPoint2().GetX(), GetPoint2().GetY()); - s.append(tmp); - sprintf(tmp, "\t\t\t\tRoom: %d <-> SubRoom: %d\n", _room->GetID(), - _subRoom->GetSubRoomID()); - s.append(tmp); - Log->Write(s); +void Hline::WriteToErrorLog() const +{ + string s; + char tmp[CLENGTH]; + sprintf(tmp, "\t\tHline: %d (%f, %f) -- (%f, %f)\n", GetID(), GetPoint1().GetX(), + GetPoint1().GetY(), GetPoint2().GetX(), GetPoint2().GetY()); + s.append(tmp); + sprintf(tmp, "\t\t\t\tRoom: %d <-> SubRoom: %d\n", _room->GetID(), + _subRoom->GetSubRoomID()); + s.append(tmp); + Log->Write(s); } // TraVisTo Ausgabe -string Hline::WriteElement() const { - string geometry; - char tmp[CLENGTH] = ""; - sprintf(tmp,"\t\t<door ID=\"%d\" color = \"250\" caption=\"%d_%d\">\n",GetUniqueID(),GetID(),GetUniqueID()); - geometry.append(tmp); - //geometry.append("\t\t<door color=\"250\">\n"); - sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", - (GetPoint1().GetX()) * FAKTOR, - (GetPoint1().GetY()) * FAKTOR, - _subRoom->GetElevation(GetPoint1())*FAKTOR); - geometry.append(tmp); - sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", - (GetPoint2().GetX()) * FAKTOR, - (GetPoint2().GetY()) * FAKTOR, - _subRoom->GetElevation(GetPoint2())*FAKTOR); - geometry.append(tmp); - geometry.append("\t\t</door>\n"); - return geometry; +string Hline::WriteElement() const +{ + string geometry; + char tmp[CLENGTH] = ""; + sprintf(tmp,"\t\t<door ID=\"%d\" color = \"250\" caption=\"%d_%d\">\n",GetUniqueID(),GetID(),GetUniqueID()); + geometry.append(tmp); + //geometry.append("\t\t<door color=\"250\">\n"); + sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", + (GetPoint1().GetX()) * FAKTOR, + (GetPoint1().GetY()) * FAKTOR, + _subRoom->GetElevation(GetPoint1())*FAKTOR); + geometry.append(tmp); + sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", + (GetPoint2().GetX()) * FAKTOR, + (GetPoint2().GetY()) * FAKTOR, + _subRoom->GetElevation(GetPoint2())*FAKTOR); + geometry.append(tmp); + geometry.append("\t\t</door>\n"); + return geometry; } diff --git a/geometry/Hline.h b/geometry/Hline.h index 64d33619bf9aa201360238359ac66ec8e96b3a7c..2819a845f98ec90e91e3432aefb4fc64d055d479 100644 --- a/geometry/Hline.h +++ b/geometry/Hline.h @@ -38,77 +38,77 @@ class Room; class Hline: public NavLine { - private: - int _id; - Room* _room; - std::string _caption; - SubRoom* _subRoom; - - public: - Hline(); - virtual ~Hline(); - - /** - * Set/Get the id of the line - */ - void SetID(int ID); - - /** - * Set/Get the Room containing this line - */ - void SetRoom(Room* r); - - /** - * Set/Get the line caption - */ - void SetCaption(std::string s); - - /** - * Set/Get the subroom containing this line - */ - void SetSubRoom(SubRoom* r); - - - /** - * Set/Get the id of the line - */ - int GetID() const; - - /** - * Set/Get the line caption - */ - std::string GetCaption() const; - - /** - * Set/Get the Room containing this line - */ - Room* GetRoom() const; - - /** - * Set/Get the subroom containing this line - */ - SubRoom* GetSubRoom() const; - - - /** - * @return true if the line is in the given subroom - */ - bool IsInSubRoom(int subroomID) const; - - /** - * @return true if the line is in the given room - */ - bool IsInRoom(int roomID) const; - - /** - * Debug output - */ - void WriteToErrorLog() const; - - /** - * @return a nicely formatted string representation of the object - */ - std::string WriteElement() const; +private: + int _id; + Room* _room; + std::string _caption; + SubRoom* _subRoom; + +public: + Hline(); + virtual ~Hline(); + + /** + * Set/Get the id of the line + */ + void SetID(int ID); + + /** + * Set/Get the Room containing this line + */ + void SetRoom(Room* r); + + /** + * Set/Get the line caption + */ + void SetCaption(std::string s); + + /** + * Set/Get the subroom containing this line + */ + void SetSubRoom(SubRoom* r); + + + /** + * Set/Get the id of the line + */ + int GetID() const; + + /** + * Set/Get the line caption + */ + std::string GetCaption() const; + + /** + * Set/Get the Room containing this line + */ + Room* GetRoom() const; + + /** + * Set/Get the subroom containing this line + */ + SubRoom* GetSubRoom() const; + + + /** + * @return true if the line is in the given subroom + */ + bool IsInSubRoom(int subroomID) const; + + /** + * @return true if the line is in the given room + */ + bool IsInRoom(int roomID) const; + + /** + * Debug output + */ + void WriteToErrorLog() const; + + /** + * @return a nicely formatted string representation of the object + */ + std::string WriteElement() const; }; #endif /* HLINE_H_ */ diff --git a/geometry/Line.cpp b/geometry/Line.cpp index 1d93e13cb3090d22ced1928d39f73c2811ca4f2f..020d0c7c4b0113e373e45b6698696154395c135a 100644 --- a/geometry/Line.cpp +++ b/geometry/Line.cpp @@ -41,77 +41,88 @@ using namespace std; /************************************************************ Konstruktoren ************************************************************/ -Line::Line() { - SetPoint1(Point()); //Default-Constructor (0.0,0.0) - SetPoint2(Point()); - _uid = _static_UID++; +Line::Line() +{ + SetPoint1(Point()); //Default-Constructor (0.0,0.0) + SetPoint2(Point()); + _uid = _static_UID++; } -Line::Line(const Point& p1, const Point& p2) { - SetPoint1(p1); - SetPoint2(p2); - _uid = _static_UID++; +Line::Line(const Point& p1, const Point& p2) +{ + SetPoint1(p1); + SetPoint2(p2); + _uid = _static_UID++; } -int Line::GetUniqueID() const { - return _uid; +int Line::GetUniqueID() const +{ + return _uid; } -Line::Line(const Line& orig) { - _point1 = orig.GetPoint1(); - _point2 = orig.GetPoint2(); - _centre = orig.GetCentre(); - _uid = orig.GetUniqueID(); +Line::Line(const Line& orig) +{ + _point1 = orig.GetPoint1(); + _point2 = orig.GetPoint2(); + _centre = orig.GetCentre(); + _uid = orig.GetUniqueID(); } -Line::~Line() { +Line::~Line() +{ } /************************************************************* Setter-Funktionen ************************************************************/ -void Line::SetPoint1(const Point& p) { - _point1 = p; - _centre = (_point1+_point2)*0.5; +void Line::SetPoint1(const Point& p) +{ + _point1 = p; + _centre = (_point1+_point2)*0.5; } -void Line::SetPoint2(const Point& p) { - _point2 = p; - _centre = (_point1+_point2)*0.5; +void Line::SetPoint2(const Point& p) +{ + _point2 = p; + _centre = (_point1+_point2)*0.5; } /************************************************************* Getter-Funktionen ************************************************************/ -const Point& Line::GetPoint1() const { - return _point1; +const Point& Line::GetPoint1() const +{ + return _point1; } -const Point& Line::GetPoint2() const { - return _point2; +const Point& Line::GetPoint2() const +{ + return _point2; } -const Point& Line::GetCentre()const { - return _centre; +const Point& Line::GetCentre()const +{ + return _centre; } /************************************************************* Ausgabe ************************************************************/ -string Line::Write() const { - string geometry; - char wall[500] = ""; - geometry.append("\t\t<wall color=\"100\">\n"); - sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n", - (GetPoint1().GetX()) * FAKTOR, - (GetPoint1().GetY()) * FAKTOR); - geometry.append(wall); - sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n", - (GetPoint2().GetX()) * FAKTOR, - (GetPoint2().GetY()) * FAKTOR); - geometry.append(wall); - geometry.append("\t\t</wall>\n"); - return geometry; +string Line::Write() const +{ + string geometry; + char wall[500] = ""; + geometry.append("\t\t<wall color=\"100\">\n"); + sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n", + (GetPoint1().GetX()) * FAKTOR, + (GetPoint1().GetY()) * FAKTOR); + geometry.append(wall); + sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n", + (GetPoint2().GetX()) * FAKTOR, + (GetPoint2().GetY()) * FAKTOR); + geometry.append(wall); + geometry.append("\t\t</wall>\n"); + return geometry; } @@ -120,87 +131,91 @@ string Line::Write() const { ************************************************************/ // Normalen vector zur Linie -Point Line::NormalVec() const { - double nx, ny, norm; - Point r = GetPoint2() - GetPoint1(); - - if (r.GetX() == 0.0) { - nx = 1; - ny = 0; - } else { - nx = -r.GetY() / r.GetX(); - ny = 1; - /* Normieren */ - norm = sqrt(nx * nx + ny * ny); - if (fabs(norm) < J_EPS) { - Log->Write("ERROR: \tLine::NormalVec() norm==0\n"); - exit(0); - } - nx /= norm; - ny /= norm; - } - return Point(nx, ny); +Point Line::NormalVec() const +{ + double nx, ny, norm; + Point r = GetPoint2() - GetPoint1(); + + if (r.GetX() == 0.0) { + nx = 1; + ny = 0; + } else { + nx = -r.GetY() / r.GetX(); + ny = 1; + /* Normieren */ + norm = sqrt(nx * nx + ny * ny); + if (fabs(norm) < J_EPS) { + Log->Write("ERROR: \tLine::NormalVec() norm==0\n"); + exit(0); + } + nx /= norm; + ny /= norm; + } + return Point(nx, ny); } // Normale Komponente von v auf l -double Line::NormalComp(const Point& v) const { - // Normierte Vectoren - Point l = (GetPoint2() - GetPoint1()).Normalized(); - const Point& n = NormalVec(); +double Line::NormalComp(const Point& v) const +{ + // Normierte Vectoren + Point l = (GetPoint2() - GetPoint1()).Normalized(); + const Point& n = NormalVec(); - double lx = l.GetX(); - double ly = l.GetY(); - double nx = n.GetX(); - double ny = n.GetY(); - double alpha; + double lx = l.GetX(); + double ly = l.GetY(); + double nx = n.GetX(); + double ny = n.GetY(); + double alpha; - if (fabs(lx) < J_EPS) { - alpha = v.GetX() / nx; - } else if (fabs(ly) < J_EPS) { - alpha = v.GetY() / ny; - } else { - alpha = (v.GetY() * lx - v.GetX() * ly) / (nx * ly - ny * lx); - } + if (fabs(lx) < J_EPS) { + alpha = v.GetX() / nx; + } else if (fabs(ly) < J_EPS) { + alpha = v.GetY() / ny; + } else { + alpha = (v.GetY() * lx - v.GetX() * ly) / (nx * ly - ny * lx); + } - return fabs(alpha); + return fabs(alpha); } // Lotfußpunkt zur Geraden Line // Muss nicht im Segment liegen -Point Line::LotPoint(const Point& p) const { - const Point& r = GetPoint1(); - const Point& s = GetPoint2(); - const Point& t = r - s; - Point tmp; - double lambda; +Point Line::LotPoint(const Point& p) const +{ + const Point& r = GetPoint1(); + const Point& s = GetPoint2(); + const Point& t = r - s; + Point tmp; + double lambda; - tmp = p - s; - lambda = tmp.ScalarP(t) / t.ScalarP(t); - Point f = s + t*lambda; - return f; + tmp = p - s; + lambda = tmp.ScalarP(t) / t.ScalarP(t); + Point f = s + t*lambda; + return f; } /* Punkt auf der Linie mit kürzestem Abstand zu p * In der Regel Lotfußpunkt, Ist der Lotfußpunkt nicht im Segment * wird der entsprechende Eckpunkt der Line genommen * */ -Point Line::ShortestPoint(const Point& p) const { +Point Line::ShortestPoint(const Point& p) const +{ - const Point& t = _point1 - _point2; + const Point& t = _point1 - _point2; - Point tmp = p - _point2; - double lambda = tmp.ScalarP(t) / t.ScalarP(t); - Point f = _point2 + t*lambda; + Point tmp = p - _point2; + double lambda = tmp.ScalarP(t) / t.ScalarP(t); + Point f = _point2 + t*lambda; - /* Prüfen ob Punkt in der Linie,sonst entsprechenden Eckpunkt zurückgeben */ - if (lambda < 0) - f = _point2; - if (lambda > 1) - f = _point1; + /* Prüfen ob Punkt in der Linie,sonst entsprechenden Eckpunkt zurückgeben */ + if (lambda < 0) + f = _point2; + if (lambda > 1) + f = _point1; - return f; + return f; } /* Prüft, ob Punkt p im Liniensegment enthalten ist @@ -234,38 +249,41 @@ Point Line::ShortestPoint(const Point& p) const { * algorithm from: * http://stackoverflow.com/questions/328107/how-can-you-determine-a-point-is-between-two-other-points-on-a-line-segment * */ -bool Line::IsInLineSegment(const Point& p) const { - //const Point& _point1 = GetPoint1(); - //const Point& _point2 = GetPoint2(); - double ax = _point1.GetX(); - double ay = _point1.GetY(); - double bx = _point2.GetX(); - double by = _point2.GetY(); - double px = p._x; - double py = p._y; - - // cross product to check if point i colinear - double crossp = (py-ay)*(bx-ax)-(px-ax)*(by-ay); - if(fabs(crossp) > J_EPS) return false; - - // dotproduct and distSquared to check if point is in segment and not just in line - double dotp = (px-ax)*(bx-ax)+(py-ay)*(by-ay); - if(dotp < 0 || (_point1-_point2).NormSquare() < dotp) return false; - - return true; - +bool Line::IsInLineSegment(const Point& p) const +{ + //const Point& _point1 = GetPoint1(); + //const Point& _point2 = GetPoint2(); + double ax = _point1.GetX(); + double ay = _point1.GetY(); + double bx = _point2.GetX(); + double by = _point2.GetY(); + double px = p._x; + double py = p._y; + + // cross product to check if point i colinear + double crossp = (py-ay)*(bx-ax)-(px-ax)*(by-ay); + if(fabs(crossp) > J_EPS) return false; + + // dotproduct and distSquared to check if point is in segment and not just in line + double dotp = (px-ax)*(bx-ax)+(py-ay)*(by-ay); + if(dotp < 0 || (_point1-_point2).NormSquare() < dotp) return false; + + return true; + } /* Berechnet direkt den Abstand von p zum Segment l * dazu wird die Funktion Line::ShortestPoint() * benuzt * */ -double Line::DistTo(const Point& p) const { - return (p - ShortestPoint(p)).Norm(); +double Line::DistTo(const Point& p) const +{ + return (p - ShortestPoint(p)).Norm(); } -double Line::DistToSquare(const Point& p) const { - return (p - ShortestPoint(p)).NormSquare(); +double Line::DistToSquare(const Point& p) const +{ + return (p - ShortestPoint(p)).NormSquare(); } // bool Line::operator*(const Line& l) const { @@ -277,341 +295,360 @@ double Line::DistToSquare(const Point& p) const { /* Zwei Linien sind gleich, wenn ihre beiden Punkte * gleich sind * */ -bool Line::operator==(const Line& l) const { - return ((_point1 == l.GetPoint1() && _point2 == l.GetPoint2()) || - (_point2 == l.GetPoint1() && _point1 == l.GetPoint2())); +bool Line::operator==(const Line& l) const +{ + return ((_point1 == l.GetPoint1() && _point2 == l.GetPoint2()) || + (_point2 == l.GetPoint1() && _point1 == l.GetPoint2())); } /* Zwei Linien sind ungleich, wenn ihre beiden Punkte * ungleich sind * */ -bool Line::operator!=(const Line& l) const { - return ((_point1 != l.GetPoint1() && _point2 != l.GetPoint2()) && - (_point2 != l.GetPoint1() && _point1 != l.GetPoint2())); +bool Line::operator!=(const Line& l) const +{ + return ((_point1 != l.GetPoint1() && _point2 != l.GetPoint2()) && + (_point2 != l.GetPoint1() && _point1 != l.GetPoint2())); } -double Line::Length() const { - return (_point1 - _point2).Norm(); +double Line::Length() const +{ + return (_point1 - _point2).Norm(); } -double Line::LengthSquare() const { - return (_point1 - _point2).NormSquare(); +double Line::LengthSquare() const +{ + return (_point1 - _point2).NormSquare(); } -bool Line::IntersectionWith(const Line& l) const { +bool Line::IntersectionWith(const Line& l) const +{ - //if(ShareCommonPointWith(l)) return true; + //if(ShareCommonPointWith(l)) return true; - double deltaACy = _point1.GetY() - l.GetPoint1().GetY(); - double deltaDCx = l.GetPoint2().GetX() - l.GetPoint1().GetX(); - double deltaACx = _point1.GetX() - l.GetPoint1().GetX(); - double deltaDCy = l.GetPoint2().GetY() - l.GetPoint1().GetY(); - double deltaBAx = _point2.GetX() - _point1.GetX(); - double deltaBAy = _point2.GetY() - _point1.GetY(); + double deltaACy = _point1.GetY() - l.GetPoint1().GetY(); + double deltaDCx = l.GetPoint2().GetX() - l.GetPoint1().GetX(); + double deltaACx = _point1.GetX() - l.GetPoint1().GetX(); + double deltaDCy = l.GetPoint2().GetY() - l.GetPoint1().GetY(); + double deltaBAx = _point2.GetX() - _point1.GetX(); + double deltaBAy = _point2.GetY() - _point1.GetY(); - double denominator = deltaBAx * deltaDCy - deltaBAy * deltaDCx; - double numerator = deltaACy * deltaDCx - deltaACx * deltaDCy; + double denominator = deltaBAx * deltaDCy - deltaBAy * deltaDCx; + double numerator = deltaACy * deltaDCx - deltaACx * deltaDCy; - // the lines are parallel - if (denominator == 0.0) { + // the lines are parallel + if (denominator == 0.0) { - // the lines are superposed - if (numerator == 0.0) { + // the lines are superposed + if (numerator == 0.0) { - // the segment are superposed - if(IsInLineSegment(l.GetPoint1()) || - IsInLineSegment(l.GetPoint2()) ) return true; - else return false; + // the segment are superposed + if(IsInLineSegment(l.GetPoint1()) || + IsInLineSegment(l.GetPoint2()) ) return true; + else return false; - } else { // the lines are just parallel and do not share a common point + } else { // the lines are just parallel and do not share a common point - return false; - } - } + return false; + } + } - // the lines intersect - double r = numerator / denominator; - if (r < 0.0 || r > 1.0) { - return false; - } + // the lines intersect + double r = numerator / denominator; + if (r < 0.0 || r > 1.0) { + return false; + } - double s = (deltaACy * deltaBAx - deltaACx * deltaBAy) / denominator; - if (s < 0.0 || s > 1.0) { - return false; - } + double s = (deltaACy * deltaBAx - deltaACx * deltaBAy) / denominator; + if (s < 0.0 || s > 1.0) { + return false; + } - //Point PointF = Point ((float) (_point1._x + r * deltaBAx), (float) (_point1._y + r * deltaBAy)); - //cout<< l.toString() << " intersects with " << toString() <<endl; - //cout<<" at point " << PointF.toString()<<endl; - return true; + //Point PointF = Point ((float) (_point1._x + r * deltaBAx), (float) (_point1._y + r * deltaBAy)); + //cout<< l.toString() << " intersects with " << toString() <<endl; + //cout<<" at point " << PointF.toString()<<endl; + return true; } -bool Line::IsHorizontal(){ - return fabs (_point1._y-_point2._y ) <= J_EPS; +bool Line::IsHorizontal() +{ + return fabs (_point1._y-_point2._y ) <= J_EPS; } -bool Line::IsVertical(){ - return fabs (_point1._x-_point2._x ) <= J_EPS; +bool Line::IsVertical() +{ + return fabs (_point1._x-_point2._x ) <= J_EPS; } -int Line::WichSide(const Point& pt) { - //special case for horizontal lines - if (IsVertical()) { - //left - if (pt._x < _point1._x) - return 0; - //right or colinear - if (pt._x >= _point1._x) - return 1; - } +int Line::WichSide(const Point& pt) +{ + //special case for horizontal lines + if (IsVertical()) { + //left + if (pt._x < _point1._x) + return 0; + //right or colinear + if (pt._x >= _point1._x) + return 1; + } - return ((_point2._x - _point1._x) * (pt._y - _point1._y) - - (_point2._y - _point1._y) * (pt._x - _point1._x)) > 0; + return ((_point2._x - _point1._x) * (pt._y - _point1._y) + - (_point2._y - _point1._y) * (pt._x - _point1._x)) > 0; } -bool Line::ShareCommonPointWith(const Line& line) const { - if(line.GetPoint1()==_point1) return true; - if(line.GetPoint2()==_point1) return true; +bool Line::ShareCommonPointWith(const Line& line) const +{ + if(line.GetPoint1()==_point1) return true; + if(line.GetPoint2()==_point1) return true; - if(line.GetPoint1()==_point2) return true; - if(line.GetPoint2()==_point2) return true; + if(line.GetPoint1()==_point2) return true; + if(line.GetPoint2()==_point2) return true; - return false; + return false; } -bool Line::HasEndPoint(const Point& point) const { - if (_point1==point) return true; - if (_point2==point) return true; - return false; +bool Line::HasEndPoint(const Point& point) const +{ + if (_point1==point) return true; + if (_point2==point) return true; + return false; } -bool Line::IntersectionWithCircle(const Point& centre, double radius /*cm for pedestrians*/){ +bool Line::IntersectionWithCircle(const Point& centre, double radius /*cm for pedestrians*/) +{ - double r=radius; - double x1=_point1.GetX(); - double y1=_point1.GetY(); + double r=radius; + double x1=_point1.GetX(); + double y1=_point1.GetY(); - double x2=_point2.GetX(); - double y2=_point2.GetY(); + double x2=_point2.GetX(); + double y2=_point2.GetY(); - double xc=centre.GetX(); - double yc=centre.GetY(); + double xc=centre.GetX(); + double yc=centre.GetY(); - //this formula assumes that the circle is centered the origin. - // so we translate the complete stuff such that the circle ends up at the origin - x1=x1-xc;y1=y1-yc; - x2=x2-xc;y2=y2-yc; - //xc=xc-xc;yc=yc-yc; to make it perfect + //this formula assumes that the circle is centered the origin. + // so we translate the complete stuff such that the circle ends up at the origin + x1=x1-xc; + y1=y1-yc; + x2=x2-xc; + y2=y2-yc; + //xc=xc-xc;yc=yc-yc; to make it perfect - // we first check the intersection of the circle and the infinite line defined by the segment - double dr2=((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); - double D2=(x1*y2-x2*y1)*(x1*y2-x2*y1); - double r2=radius*radius; + // we first check the intersection of the circle and the infinite line defined by the segment + double dr2=((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)); + double D2=(x1*y2-x2*y1)*(x1*y2-x2*y1); + double r2=radius*radius; - double delta=r2*dr2-D2; - if(delta<=0.0) return false; + double delta=r2*dr2-D2; + if(delta<=0.0) return false; - double a=(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1); - double b=2*((x1*(x2-x1))+y1*(y2-y1)); - double c=x1*x1+y1*y1-r*r; + double a=(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1); + double b=2*((x1*(x2-x1))+y1*(y2-y1)); + double c=x1*x1+y1*y1-r*r; - delta=b*b-4*a*c; + delta=b*b-4*a*c; - if((x1==x2)&&(y1==y2)){ - Log->Write("isLineCrossingCircle: Your line is a point"); - return false; - } - if(delta<0.0){ - char tmp[CLENGTH]; - sprintf(tmp,"there is a bug in 'isLineCrossingCircle', delta(%f) can t be <0 at this point.",delta); - Log->Write(tmp); - Log->Write("press ENTER"); - return false; //fixme - //getc(stdin); - } + if((x1==x2)&&(y1==y2)) { + Log->Write("isLineCrossingCircle: Your line is a point"); + return false; + } + if(delta<0.0) { + char tmp[CLENGTH]; + sprintf(tmp,"there is a bug in 'isLineCrossingCircle', delta(%f) can t be <0 at this point.",delta); + Log->Write(tmp); + Log->Write("press ENTER"); + return false; //fixme + //getc(stdin); + } - double t1= (-b + sqrt(delta))/(2*a); - double t2= (-b - sqrt(delta))/(2*a); - if((t1<0.0) || (t1>1.0)) return false; - if((t2<0.0) || (t2>1.0)) return false; - return true; + double t1= (-b + sqrt(delta))/(2*a); + double t2= (-b - sqrt(delta))/(2*a); + if((t1<0.0) || (t1>1.0)) return false; + if((t2<0.0) || (t2>1.0)) return false; + return true; } //TODO: Consider numerical stability and special case pt is on line // Returns true if pt is on the left side ( from point1 toward point2) -bool Line::IsLeft(const Point& pt){ - double test=(_point2._x-_point1._x)*(pt.GetY()-_point1._y)-(_point2._y-_point1._y)*(pt.GetX()-_point1._x); - if (test>0.0) - return true; - else - return false; -} - -const Point& Line::GetLeft(const Point& pt){ - if (IsLeft(pt)){ - return _point2; - }else{ - return _point1; - } -} - -const Point& Line::GetRight(const Point& pt){ - if (!IsLeft(pt)){ - return _point2; - }else{ - return _point1; - } -} - -std::string Line::toString() const { - std::stringstream tmp; - tmp<<_point1.toString()<<"--"<<_point2.toString(); - return tmp.str(); +bool Line::IsLeft(const Point& pt) +{ + double test=(_point2._x-_point1._x)*(pt.GetY()-_point1._y)-(_point2._y-_point1._y)*(pt.GetX()-_point1._x); + if (test>0.0) + return true; + else + return false; +} + +const Point& Line::GetLeft(const Point& pt) +{ + if (IsLeft(pt)) { + return _point2; + } else { + return _point1; + } +} + +const Point& Line::GetRight(const Point& pt) +{ + if (!IsLeft(pt)) { + return _point2; + } else { + return _point1; + } +} + +std::string Line::toString() const +{ + std::stringstream tmp; + tmp<<_point1.toString()<<"--"<<_point2.toString(); + return tmp.str(); } // get distance between first point of line with the intersection point. //if no intersection return infinity // this function is exactly the same as GetIntersection(), but returns the distance squared //insteed of a boolian -double Line::GetIntersectionDistance(const Line & l) const{ - - double deltaACy = _point1.GetY() - l.GetPoint1().GetY(); - double deltaDCx = l.GetPoint2().GetX() - l.GetPoint1().GetX(); - double deltaACx = _point1.GetX() - l.GetPoint1().GetX(); - double deltaDCy = l.GetPoint2().GetY() - l.GetPoint1().GetY(); - double deltaBAx = _point2.GetX() - _point1.GetX(); - double deltaBAy = _point2.GetY() - _point1.GetY(); - - double denominator = deltaBAx * deltaDCy - deltaBAy * deltaDCx; - double numerator = deltaACy * deltaDCx - deltaACx * deltaDCy; - double infinity =100000; - // the lines are parallel - if (denominator == 0.0) { - - // the lines are superposed - if (numerator == 0.0) { - - // the segment are superposed - if(IsInLineSegment(l.GetPoint1()) || - IsInLineSegment(l.GetPoint2()) ) return infinity;//really? - else return infinity; - - } else { // the lines are just parallel and do not share a common point - - return infinity; - } - } - - // the lines intersect - double r = numerator / denominator; - if (r < 0.0 || r > 1.0) { - return infinity; - } - - double s = (deltaACy * deltaBAx - deltaACx * deltaBAy) / denominator; - if (s < 0.0 || s > 1.0) { - return infinity; - } - - Point PointF = Point ((float) (_point1._x + r * deltaBAx), (float) (_point1._y + r * deltaBAy)); - double dist = (_point1-PointF).NormSquare(); - //cout<< " MC Line.cpp 516" << l.toString() << " intersects with " << toString() <<endl; - //cout<<" at point " << PointF.toString()<<endl; - //cout << "distance is "<< sqrt(dist)<< "... return "<< dist<<endl; - return dist; +double Line::GetIntersectionDistance(const Line & l) const +{ + + double deltaACy = _point1.GetY() - l.GetPoint1().GetY(); + double deltaDCx = l.GetPoint2().GetX() - l.GetPoint1().GetX(); + double deltaACx = _point1.GetX() - l.GetPoint1().GetX(); + double deltaDCy = l.GetPoint2().GetY() - l.GetPoint1().GetY(); + double deltaBAx = _point2.GetX() - _point1.GetX(); + double deltaBAy = _point2.GetY() - _point1.GetY(); + + double denominator = deltaBAx * deltaDCy - deltaBAy * deltaDCx; + double numerator = deltaACy * deltaDCx - deltaACx * deltaDCy; + double infinity =100000; + // the lines are parallel + if (denominator == 0.0) { + + // the lines are superposed + if (numerator == 0.0) { + + // the segment are superposed + if(IsInLineSegment(l.GetPoint1()) || + IsInLineSegment(l.GetPoint2()) ) return infinity;//really? + else return infinity; + + } else { // the lines are just parallel and do not share a common point + + return infinity; + } + } + + // the lines intersect + double r = numerator / denominator; + if (r < 0.0 || r > 1.0) { + return infinity; + } + + double s = (deltaACy * deltaBAx - deltaACx * deltaBAy) / denominator; + if (s < 0.0 || s > 1.0) { + return infinity; + } + + Point PointF = Point ((float) (_point1._x + r * deltaBAx), (float) (_point1._y + r * deltaBAy)); + double dist = (_point1-PointF).NormSquare(); + //cout<< " MC Line.cpp 516" << l.toString() << " intersects with " << toString() <<endl; + //cout<<" at point " << PointF.toString()<<endl; + //cout << "distance is "<< sqrt(dist)<< "... return "<< dist<<endl; + return dist; } //sign of the angle depends on the direction of the wall (l). -//the second point of l should be the nearest to the goal. -//the goal in the intended use case is the second point of -//the calling line +//the second point of l should be the nearest to the goal. +//the goal in the intended use case is the second point of +//the calling line // -double Line::GetAngle(const Line & l) const{ - const double pi= atan(1)*4; - double ax = _point1.GetX(); - double ay = _point1.GetY(); - double bx = _point2.GetX(); - double by = _point2.GetY(); - //printf("ax=%f, ay=%f --- bx=%f, by=%f\n", ax, ay, bx, by); - double diff_x1 = bx - ax; - double diff_y1 = by - ay; - // printf("diff_x1=%f, diff_y1=%f\n", diff_x1, diff_y1); - double cx =l.GetPoint1().GetX(); - double cy =l.GetPoint1().GetY(); - double dx =l.GetPoint2().GetX(); - double dy =l.GetPoint2().GetY(); - //printf("cx=%f, cy=%f --- dx=%f, dy=%f\n", cx, cy, dx, dy); - - double diff_x2 = dx - cx; - double diff_y2 = dy - cy; - // printf("diff_x2=%f, diff_y2=%f\n", diff_x2, diff_y2); - - double atanA = atan2( diff_y1, diff_x1 ); - double atanB = atan2( diff_y2, diff_x2); +double Line::GetAngle(const Line & l) const +{ + const double pi= atan(1)*4; + double ax = _point1.GetX(); + double ay = _point1.GetY(); + double bx = _point2.GetX(); + double by = _point2.GetY(); + //printf("ax=%f, ay=%f --- bx=%f, by=%f\n", ax, ay, bx, by); + double diff_x1 = bx - ax; + double diff_y1 = by - ay; + // printf("diff_x1=%f, diff_y1=%f\n", diff_x1, diff_y1); + double cx =l.GetPoint1().GetX(); + double cy =l.GetPoint1().GetY(); + double dx =l.GetPoint2().GetX(); + double dy =l.GetPoint2().GetY(); + //printf("cx=%f, cy=%f --- dx=%f, dy=%f\n", cx, cy, dx, dy); + + double diff_x2 = dx - cx; + double diff_y2 = dy - cy; + // printf("diff_x2=%f, diff_y2=%f\n", diff_x2, diff_y2); + + double atanA = atan2( diff_y1, diff_x1 ); + double atanB = atan2( diff_y2, diff_x2); // printf("atanA %f atanB %f\n", atanA*180/pi, atanB*180/pi); - double angle = atanA - atanB; - - - double absAngle= fabs(angle); - double sign = (angle <0)? -1.0 : 1.0; - - - // if (angle>pi) - // printf( "NORMALIZE --> %.2f\n", (2*pi-angle)*180/pi); - angle = (angle>pi)? -(2*pi-absAngle): angle; - //printf("angle=%.2f, absAngle=%.2f, sign=%.1f\n", angle*180/pi, absAngle, sign); - - absAngle= fabs(angle); - double tmp = (absAngle<pi/2)? (-angle) : (pi-absAngle)*sign; - - //printf("tmp=%.2f exp=%.2f\n", tmp, (pi-absAngle)*sign); - - // 3pi/4 ----> pi/4 (sign=1) - // -3pi/4 ----> -pi/4 (sign=-1) - // pi/4 ----> -pi/4 - // -pi/4 ----> pi/4 - - return tmp; - - - - // double distPoint2ToGoalSq = (dx-bx)*(dx-bx) + (dy-by)*(dy-by); - // double distPoint1ToGoalSq = (cx-bx)*(cx-bx) + (cy-by)*(cy-by); - // if(distPoint1ToGoalSq < distPoint2ToGoalSq) //invert the line - // { - // double tx = dx, ty = dy; - // dx = cx; dy = cy; - // cx = tx; cy = ty; - // } - - // double dotp = (bx-ax)*(dx-cx)+(by-ay)*(dy-cy); - // double len, len1; - - // len = l.Length(); - // if (len < J_EPS) - // return 0; - - // len1 = this->Length(); - - // if (len1 < J_EPS) - // return 0; - - - // double angle = acos( dotp / (len * len1) ); - // double crossp = (bx-ax)*(dy-cy) - (by-ay)*(dx-cx); - // double sign = (crossp <0)? -1.0 : 1.0; - - - - // angle = (angle<pi/2)?angle:pi-angle; - // return angle*sign; - + double angle = atanA - atanB; + + + double absAngle= fabs(angle); + double sign = (angle <0)? -1.0 : 1.0; + + + // if (angle>pi) + // printf( "NORMALIZE --> %.2f\n", (2*pi-angle)*180/pi); + angle = (angle>pi)? -(2*pi-absAngle): angle; + //printf("angle=%.2f, absAngle=%.2f, sign=%.1f\n", angle*180/pi, absAngle, sign); + + absAngle= fabs(angle); + double tmp = (absAngle<pi/2)? (-angle) : (pi-absAngle)*sign; + + //printf("tmp=%.2f exp=%.2f\n", tmp, (pi-absAngle)*sign); + + // 3pi/4 ----> pi/4 (sign=1) + // -3pi/4 ----> -pi/4 (sign=-1) + // pi/4 ----> -pi/4 + // -pi/4 ----> pi/4 + + return tmp; + + + + // double distPoint2ToGoalSq = (dx-bx)*(dx-bx) + (dy-by)*(dy-by); + // double distPoint1ToGoalSq = (cx-bx)*(cx-bx) + (cy-by)*(cy-by); + // if(distPoint1ToGoalSq < distPoint2ToGoalSq) //invert the line + // { + // double tx = dx, ty = dy; + // dx = cx; dy = cy; + // cx = tx; cy = ty; + // } + + // double dotp = (bx-ax)*(dx-cx)+(by-ay)*(dy-cy); + // double len, len1; + + // len = l.Length(); + // if (len < J_EPS) + // return 0; + + // len1 = this->Length(); + + // if (len1 < J_EPS) + // return 0; + + + // double angle = acos( dotp / (len * len1) ); + // double crossp = (bx-ax)*(dy-cy) - (by-ay)*(dx-cx); + // double sign = (crossp <0)? -1.0 : 1.0; + + + + // angle = (angle<pi/2)?angle:pi-angle; + // return angle*sign; + } // get the angle that is needed to turn a line, so that it -// doen not intersect the nearest Wall in subroom +// doen not intersect the nearest Wall in subroom // double Line::GetAngle(SubRoom * subroom) const{ // double dist; // int inear = -1; @@ -629,7 +666,7 @@ double Line::GetAngle(const Line & l) const{ // } // }//walls // //============================ WALLS =========================== - + // //============================ OBST =========================== // const vector<Obstacle*>& obstacles = subroom->GetAllObstacles(); // for(unsigned int obs=0; obs<obstacles.size(); ++obs){ @@ -653,7 +690,7 @@ double Line::GetAngle(const Line & l) const{ // if(iObs >= 0) // { // const vector<Wall>& owalls = obstacles[iObs]->GetAllWalls(); -// angle = tmpDirection.GetAngle(owalls[inear]); +// angle = tmpDirection.GetAngle(owalls[inear]); // } // else // angle = tmpDirection.GetAngle(walls[inear]); diff --git a/geometry/Line.h b/geometry/Line.h index 1b43fe5da45ef9f526cc6b2ef6c1ec52d37a2b4a..0db8941bbf623bf04583718a1b6bef121d0a6788 100644 --- a/geometry/Line.h +++ b/geometry/Line.h @@ -40,198 +40,198 @@ extern OutputHandler* Log; class Line { - private: - Point _point1; - Point _point2; - Point _centre; - - //unique identifier for all line elements - static int _static_UID; - int _uid; - - public: - - Line(); - Line(const Point& p1, const Point& p2); - Line(const Line& orig); - virtual ~Line(); - - /** - * All Line elements (also derived class) have a unique ID - * @return the unique ID of this line element. - */ - int GetUniqueID() const; - - /** - * Set/Get the first end point of the line - */ - void SetPoint1(const Point& p); - - /** - * Set/Get the second end point of the line - */ - void SetPoint2(const Point& p); - - /** - * Set/Get the first end point of the line - */ - const Point& GetPoint1(void) const; - - /** - * Set/Get the second end point of the line - */ - const Point& GetPoint2(void) const; - - /** - * Return the center of the line - */ - const Point& GetCentre(void) const; - - /** - * @return a normal vector to this line - */ - Point NormalVec() const; // Normalen_Vector zu Line - - /** - *TODO: FIXME - */ - double NormalComp(const Point& v) const; // Normale Komponente von v auf l - - /** - * Note that that result must not lie on the segment - * @return the orthogonal projection of p on the line defined by the segment points. - */ - Point LotPoint(const Point& p) const; - - /** - * @return the point on the segment with the minimum distance to p - */ - Point ShortestPoint(const Point& p) const; - - /** - * @return true if the point p lies on the line defined by the first and the second point - */ - bool IsInLine(const Point& p) const; - - /** - * @see IsInLine - * @return true if the point p is within the line segment defined the line end points - */ - bool IsInLineSegment(const Point& p) const; - - /** - * @return the distance from the line to the point p - */ - double DistTo(const Point& p) const; - - /** - * @return the distance square from the line to the point p - */ - double DistToSquare(const Point& p) const; - - /** - * @return the length (Norm) of the line - */ - double Length() const; - - /** - * @return the lenght square of the segment - */ - double LengthSquare() const; - - /* /\** */ - /* * @return dot product of two lines */ - /* *\/ */ - /* bool operator*(const Line& l) const; */ - - /** - * @return true if both segments are equal. The end points must be in the range of J_EPS. - * @see Macro.h - */ - bool operator==(const Line& l) const; - - /** - * @return true if both segments are not equal. The end points must be in the range of J_EPS. - * @see Macro.h - */ - bool operator!=(const Line& l) const; - - /** - * @see http://alienryderflex.com/intersect/ - * @see http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/e5993847-c7a9-46ec-8edc-bfb86bd689e3/ - * @return true if both segments intersect - */ - bool IntersectionWith(const Line& l) const; // check two segments for intersections - - /** - * @return the distance squared between the first point and the intersection - * point with line l. This is exactly the same function - * as @see IntersectionWith() but returns a double insteed. - */ - double GetIntersectionDistance(const Line & l ) const; - /** - * @return true if the segment intersects with the circle of radius r - */ - bool IntersectionWithCircle(const Point& centre, double radius=0.30 /*m for pedestrians*/); - - - /** - * @return true if both segments share at least one common point - */ - bool ShareCommonPointWith(const Line& line) const; - - /** - * @return true if the given point is one end point of the segment - */ - bool HasEndPoint(const Point& point) const; - - /** - * return the same value if the checked points are all situated on the same side. - * @return 0 or 1 depending on which side of the line the point is located. - */ - int WichSide (const Point& pt); - - /** - * @return true if the point is located in the left hand side of the line. - * For horizontal lines return true if the point is above the line. - */ - bool IsLeft (const Point& pt); - - /** - * @return true for horizontal lines - */ - bool IsHorizontal(); - - /** - * @return true for vertical lines - */ - bool IsVertical(); - - /** - * @return left point wrt. the point pt - */ - const Point& GetLeft(const Point& pt); - - /** - * @return left point wrt. the point pt - */ - const Point& GetRight(const Point& pt); - - /** - * @return a nice formated string describing the line - */ - virtual std::string Write() const; - - /** - * @return a nice formated string describing the line - */ - std::string toString() const; - - /** - * @return the angle between two lines - */ - double GetAngle(const Line& l) const; - // double GetAngle(SubRoom s) const; +private: + Point _point1; + Point _point2; + Point _centre; + + //unique identifier for all line elements + static int _static_UID; + int _uid; + +public: + + Line(); + Line(const Point& p1, const Point& p2); + Line(const Line& orig); + virtual ~Line(); + + /** + * All Line elements (also derived class) have a unique ID + * @return the unique ID of this line element. + */ + int GetUniqueID() const; + + /** + * Set/Get the first end point of the line + */ + void SetPoint1(const Point& p); + + /** + * Set/Get the second end point of the line + */ + void SetPoint2(const Point& p); + + /** + * Set/Get the first end point of the line + */ + const Point& GetPoint1(void) const; + + /** + * Set/Get the second end point of the line + */ + const Point& GetPoint2(void) const; + + /** + * Return the center of the line + */ + const Point& GetCentre(void) const; + + /** + * @return a normal vector to this line + */ + Point NormalVec() const; // Normalen_Vector zu Line + + /** + *TODO: FIXME + */ + double NormalComp(const Point& v) const; // Normale Komponente von v auf l + + /** + * Note that that result must not lie on the segment + * @return the orthogonal projection of p on the line defined by the segment points. + */ + Point LotPoint(const Point& p) const; + + /** + * @return the point on the segment with the minimum distance to p + */ + Point ShortestPoint(const Point& p) const; + + /** + * @return true if the point p lies on the line defined by the first and the second point + */ + bool IsInLine(const Point& p) const; + + /** + * @see IsInLine + * @return true if the point p is within the line segment defined the line end points + */ + bool IsInLineSegment(const Point& p) const; + + /** + * @return the distance from the line to the point p + */ + double DistTo(const Point& p) const; + + /** + * @return the distance square from the line to the point p + */ + double DistToSquare(const Point& p) const; + + /** + * @return the length (Norm) of the line + */ + double Length() const; + + /** + * @return the lenght square of the segment + */ + double LengthSquare() const; + + /* /\** */ + /* * @return dot product of two lines */ + /* *\/ */ + /* bool operator*(const Line& l) const; */ + + /** + * @return true if both segments are equal. The end points must be in the range of J_EPS. + * @see Macro.h + */ + bool operator==(const Line& l) const; + + /** + * @return true if both segments are not equal. The end points must be in the range of J_EPS. + * @see Macro.h + */ + bool operator!=(const Line& l) const; + + /** + * @see http://alienryderflex.com/intersect/ + * @see http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/e5993847-c7a9-46ec-8edc-bfb86bd689e3/ + * @return true if both segments intersect + */ + bool IntersectionWith(const Line& l) const; // check two segments for intersections + + /** + * @return the distance squared between the first point and the intersection + * point with line l. This is exactly the same function + * as @see IntersectionWith() but returns a double insteed. + */ + double GetIntersectionDistance(const Line & l ) const; + /** + * @return true if the segment intersects with the circle of radius r + */ + bool IntersectionWithCircle(const Point& centre, double radius=0.30 /*m for pedestrians*/); + + + /** + * @return true if both segments share at least one common point + */ + bool ShareCommonPointWith(const Line& line) const; + + /** + * @return true if the given point is one end point of the segment + */ + bool HasEndPoint(const Point& point) const; + + /** + * return the same value if the checked points are all situated on the same side. + * @return 0 or 1 depending on which side of the line the point is located. + */ + int WichSide (const Point& pt); + + /** + * @return true if the point is located in the left hand side of the line. + * For horizontal lines return true if the point is above the line. + */ + bool IsLeft (const Point& pt); + + /** + * @return true for horizontal lines + */ + bool IsHorizontal(); + + /** + * @return true for vertical lines + */ + bool IsVertical(); + + /** + * @return left point wrt. the point pt + */ + const Point& GetLeft(const Point& pt); + + /** + * @return left point wrt. the point pt + */ + const Point& GetRight(const Point& pt); + + /** + * @return a nice formated string describing the line + */ + virtual std::string Write() const; + + /** + * @return a nice formated string describing the line + */ + std::string toString() const; + + /** + * @return the angle between two lines + */ + double GetAngle(const Line& l) const; + // double GetAngle(SubRoom s) const; }; diff --git a/geometry/NavLine.cpp b/geometry/NavLine.cpp index ade179a33d520ace2144c3be73eb4e6cec455ee4..5f3cfc37aafc9b4e8b26c92ff51a3ad68f280b8d 100644 --- a/geometry/NavLine.cpp +++ b/geometry/NavLine.cpp @@ -30,15 +30,18 @@ -NavLine::NavLine() { +NavLine::NavLine() +{ } -NavLine::NavLine(Line l):Line(l) { +NavLine::NavLine(Line l):Line(l) +{ } -NavLine::~NavLine() { +NavLine::~NavLine() +{ } diff --git a/geometry/NavLine.h b/geometry/NavLine.h index 205a63ec5e84270a360f22199c57ef6bd7578fe7..594df84e73ae34ac795a9358b85ef4eab052d0d1 100644 --- a/geometry/NavLine.h +++ b/geometry/NavLine.h @@ -32,10 +32,10 @@ class NavLine: public Line { - public: - NavLine(); - NavLine(Line l); - virtual ~NavLine(); +public: + NavLine(); + NavLine(Line l); + virtual ~NavLine(); }; diff --git a/geometry/Obstacle.cpp b/geometry/Obstacle.cpp index e2760d141c57931c86d9f95f907ed446c81f9589..e4d6cfd3267b86cb441837b191f129984b7934a7 100644 --- a/geometry/Obstacle.cpp +++ b/geometry/Obstacle.cpp @@ -44,250 +44,268 @@ using namespace std; -Obstacle::Obstacle() { - _isClosed=0.0; - _height=0.0; - _id=-1; - _caption="obstacle"; - _walls = vector<Wall > (); - _poly = vector<Point > (); +Obstacle::Obstacle() +{ + _isClosed=0.0; + _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); +void Obstacle::AddWall(const Wall& w) +{ + _walls.push_back(w); } -string Obstacle::GetCaption() const { - return _caption; +string Obstacle::GetCaption() const +{ + return _caption; } -void Obstacle::SetCaption(string caption) { - _caption = caption; +void Obstacle::SetCaption(string caption) +{ + _caption = caption; } -double Obstacle::GetClosed() const { - return _isClosed; +double Obstacle::GetClosed() const +{ + return _isClosed; } -void Obstacle::SetClosed(double closed) { - _isClosed = closed; +void Obstacle::SetClosed(double closed) +{ + _isClosed = closed; } -double Obstacle::GetHeight() const { - return _height; +double Obstacle::GetHeight() const +{ + return _height; } -void Obstacle::SetHeight(double height) { - _height = height; +void Obstacle::SetHeight(double height) +{ + _height = height; } -int Obstacle::GetId() const { - return _id; +int Obstacle::GetId() const +{ + return _id; } -void Obstacle::SetId(int id) { - _id = id; +void Obstacle::SetId(int id) +{ + _id = id; } -const vector<Point>& Obstacle::GetPolygon() const { - return _poly; +const vector<Point>& Obstacle::GetPolygon() const +{ + return _poly; } -string Obstacle::Write() { - string s; - //Point pos; +string Obstacle::Write() +{ + string s; + //Point pos; - 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()); + 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(); + 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()); + //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); + 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; + return s; } -const vector<Wall>& Obstacle::GetAllWalls() const { - return _walls; +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); +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); } // 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()))); +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 { - - // in the case the obstacle is not a close surface, allow - // pedestrians distribution 'inside' - if(_isClosed==0.0) { - char tmp[CLENGTH]; - sprintf(tmp, "ERROR: \tObstacle::Contains(): the obstacle [%d] is open!!!\n", _id); - Log->Write(tmp); - exit(EXIT_FAILURE); - } - - 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::Contains(const Point& ped) const +{ + + // in the case the obstacle is not a close surface, allow + // pedestrians distribution 'inside' + if(_isClosed==0.0) { + char tmp[CLENGTH]; + sprintf(tmp, "ERROR: \tObstacle::Contains(): the obstacle [%d] is open!!!\n", _id); + Log->Write(tmp); + exit(EXIT_FAILURE); + } + + 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; } -void Obstacle::ConvertLineToPoly() { - - if(_isClosed==0.0){ - char tmp[CLENGTH]; - sprintf(tmp, "INFO: \tObstacle [%d] is not closed. Not converting to polyline.\n", _id); - Log->Write(tmp); - return; - } - vector<Line*> copy; - vector<Point> tmpPoly; - Point point; - Line* line; - // Alle Linienelemente in copy speichern - for (unsigned int i = 0; i < _walls.size(); i++) { - copy.push_back(&_walls[i]); - } - - 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); - exit(0); - } - _poly = tmpPoly; +void Obstacle::ConvertLineToPoly() +{ + + if(_isClosed==0.0) { + char tmp[CLENGTH]; + sprintf(tmp, "INFO: \tObstacle [%d] is not closed. Not converting to polyline.\n", _id); + Log->Write(tmp); + return; + } + vector<Line*> copy; + vector<Point> tmpPoly; + Point point; + Line* line; + // Alle Linienelemente in copy speichern + for (unsigned int i = 0; i < _walls.size(); i++) { + copy.push_back(&_walls[i]); + } + + 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); + exit(0); + } + _poly = tmpPoly; } -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); +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::IntersectWithLine(const Line& line) const { +bool Obstacle::IntersectWithLine(const Line& line) const +{ - for (unsigned int i=0;i<_walls.size();i++){ + for (unsigned int i=0; i<_walls.size(); i++) { - if(_walls[i].IntersectionWith(line)) return true; - } + if(_walls[i].IntersectionWith(line)) return true; + } - return false; + return false; } diff --git a/geometry/Obstacle.h b/geometry/Obstacle.h index 7a397f034876a8203a36d2c1ba3b34003af660d4..f3d066c8d4f0f702dd5e52f5ec113972682ecc08 100644 --- a/geometry/Obstacle.h +++ b/geometry/Obstacle.h @@ -38,108 +38,108 @@ class Obstacle { - private: - double _isClosed; - double _height; - int _id; - std::string _caption; - std::vector<Wall> _walls; - std::vector<Point> _poly; - - public: - Obstacle(); - virtual ~Obstacle(); - - /** - * Set/Get the obstacles' caption - */ - std::string GetCaption() const; - - /** - * Set/Get the obstacles' caption - */ - void SetCaption(std::string caption); - - /** - * Set/Get the close state of the obstacle - */ - double GetClosed() const; - - /** - * Set/Get the close state of the obstacle - */ - void SetClosed(double closed); - - /** - * Set/Get the height of the obstacle. - * Is used for computing visibility - */ - double GetHeight() const; - - /** - * Set/Get the height of the obstacle. - * Is used for computing visibility - */ - void SetHeight(double height); - - /** - * Set/Get the id of the obstacle - */ - int GetId() const; - - /** - * Set/Get the id of the obstacle - */ - void SetId(int id); - - /** - * construct the obstacle by adding more walls - */ - void AddWall(const Wall& w); - - /** - * @return All walls that constitute the obstacle - */ - const std::vector<Wall>& GetAllWalls() const; - - /** - * @return true if the point p is contained within the Closed Obstacle - * @see Setclose - */ - bool Contains(const Point& p) const; - - /** - * Create the obstacles polygonal structure from the walls - */ - void ConvertLineToPoly(); - - /** - * @return the obstacle as a polygon - */ - const std::vector<Point>& GetPolygon() const; - - /** - * @return the centroid of the obstacle - */ - const Point GetCentroid() const; - - /** - * return true if the given line intersects - * or share common vertex with the obstacle - */ - bool IntersectWithLine(const Line & line) const; - - /** - * @return a nicely formatted string representation of the obstacle - */ - std::string Write(); - - private: - int WhichQuad(const Point& vertex, const Point& hitPos) const; - - // x-Koordinate der Linie von einer Eccke zur nächsten - double Xintercept(const Point& point1, const Point& point2, - double hitY) const; +private: + double _isClosed; + double _height; + int _id; + std::string _caption; + std::vector<Wall> _walls; + std::vector<Point> _poly; + +public: + Obstacle(); + virtual ~Obstacle(); + + /** + * Set/Get the obstacles' caption + */ + std::string GetCaption() const; + + /** + * Set/Get the obstacles' caption + */ + void SetCaption(std::string caption); + + /** + * Set/Get the close state of the obstacle + */ + double GetClosed() const; + + /** + * Set/Get the close state of the obstacle + */ + void SetClosed(double closed); + + /** + * Set/Get the height of the obstacle. + * Is used for computing visibility + */ + double GetHeight() const; + + /** + * Set/Get the height of the obstacle. + * Is used for computing visibility + */ + void SetHeight(double height); + + /** + * Set/Get the id of the obstacle + */ + int GetId() const; + + /** + * Set/Get the id of the obstacle + */ + void SetId(int id); + + /** + * construct the obstacle by adding more walls + */ + void AddWall(const Wall& w); + + /** + * @return All walls that constitute the obstacle + */ + const std::vector<Wall>& GetAllWalls() const; + + /** + * @return true if the point p is contained within the Closed Obstacle + * @see Setclose + */ + bool Contains(const Point& p) const; + + /** + * Create the obstacles polygonal structure from the walls + */ + void ConvertLineToPoly(); + + /** + * @return the obstacle as a polygon + */ + const std::vector<Point>& GetPolygon() const; + + /** + * @return the centroid of the obstacle + */ + const Point GetCentroid() const; + + /** + * return true if the given line intersects + * or share common vertex with the obstacle + */ + bool IntersectWithLine(const Line & line) const; + + /** + * @return a nicely formatted string representation of the obstacle + */ + std::string Write(); + +private: + int WhichQuad(const Point& vertex, const Point& hitPos) const; + + // x-Koordinate der Linie von einer Eccke zur nächsten + double Xintercept(const Point& point1, const Point& point2, + double hitY) const; }; diff --git a/geometry/Point.cpp b/geometry/Point.cpp index 4ebaf4b28df993f554b4bfc665566de28ba876c5..d2500120aa196d632d74db89b4d609b11afaf015 100644 --- a/geometry/Point.cpp +++ b/geometry/Point.cpp @@ -1,6 +1,6 @@ /** * File: Point.cpp - * + * * Created on 30. September 2010, 09:21 * @section LICENSE * This file is part of JuPedSim. @@ -38,67 +38,80 @@ /************************************************************ Konstruktoren ************************************************************/ -Point::Point() { - _x = 0.0; - _y = 0.0; +Point::Point() +{ + _x = 0.0; + _y = 0.0; } -Point::Point(double x, double y) { - _x = x; - _y = y; +Point::Point(double x, double y) +{ + _x = x; + _y = y; } -Point::Point(const Point& orig) { - _x = orig.GetX(); - _y = orig.GetY(); +Point::Point(const Point& orig) +{ + _x = orig.GetX(); + _y = orig.GetY(); } -std::string Point::toString() const { - std::stringstream tmp; - tmp<<"( "<<_x<<" : " <<_y<<" )"; - return tmp.str(); +std::string Point::toString() const +{ + std::stringstream tmp; + tmp<<"( "<<_x<<" : " <<_y<<" )"; + return tmp.str(); }; -void Point::SetX(double x) { - _x = x; +void Point::SetX(double x) +{ + _x = x; } -void Point::SetY(double y) { - _y = y; +void Point::SetY(double y) +{ + _y = y; } -double Point::GetX() const { - return _x; +double Point::GetX() const +{ + return _x; } -double Point::GetY() const { - return _y; +double Point::GetY() const +{ + return _y; } -double Point::Norm() const { - return sqrt(_x * _x + _y * _y); +double Point::Norm() const +{ + return sqrt(_x * _x + _y * _y); } -double Point::NormSquare() const { - return (_x * _x + _y * _y); +double Point::NormSquare() const +{ + return (_x * _x + _y * _y); } -Point Point::Normalized() const { - double norm=Norm(); - if (norm > J_EPS*J_EPS) - return ( Point(_x, _y) / norm ); - else return Point(0.0, 0.0); +Point Point::Normalized() const +{ + double norm=Norm(); + if (norm > J_EPS*J_EPS) + return ( Point(_x, _y) / norm ); + else return Point(0.0, 0.0); } // scalar product -double Point::ScalarP(const Point& v) const { - //return _x * v.GetX() + _y * v.GetY(); - return _x * v._x + _y * v._y; +double Point::ScalarP(const Point& v) const +{ + //return _x * v.GetX() + _y * v.GetY(); + return _x * v._x + _y * v._y; } /// determinant of the square matrix formed by the vectors [ this, v] -double Point::Det(const Point& v) const { - return _x * v._y - _y * v._x; +double Point::Det(const Point& v) const +{ + return _x * v._y - _y * v._x; } /* Transformiert die "normalen" Koordinaten in Koordinaten der Ellipse @@ -110,13 +123,13 @@ double Point::Det(const Point& v) const { /*coordinate transformation of the point P(x,y) expressed in coord system S1 to a new coord. sys S2 - + A - * - | S_2 - \ | / - | \ | / - | \ | /^phi + * + | S_2 + \ | / + | \ | / + | \ | /^phi | yc___\ /_)_________ S_3 | O1 | | @@ -129,17 +142,17 @@ S_1 //////////////////////////////////// -S_1 is cartesian coordinate system!! +S_1 is cartesian coordinate system!! //////////////////////////////////// input: - (x,y) : coordinates of the point A in S_1 - (xc,yc) : coordinate of the center in the S_1 (Center of Ellipse) - phi : angle between the S_1 and S_2 - + output: - + (xnew,ynew) : new coordinate of the point A in the coord. sys S2 - + + (xnew,ynew) : new coordinate of the point A in the coord. sys S2 + OA = OO1 + O1A [x ; y] = [xc ; yc] + [x_3 ; y_3] : (1) ( with [x_i ; y_i] coordinats of P in S_i and i in {1,2,3} ) @@ -147,7 +160,7 @@ OA = OO1 + O1A [x_2 ; y_2] = M(phi) * [x_3 ; y_3] : (2) -(1) in (2)---> +(1) in (2)---> --> [x_2 ; y_2] = M(phi) * ([x ; y] - [xc ; yc]) @@ -158,22 +171,23 @@ OC = OO1 +O1C OC = -O1O +O1C xnew = -xc + x - + */ -Point Point::CoordTransToEllipse(const Point& center, double cphi, double sphi) const { - Point p = Point(_x, _y); - return (p - center).Rotate(cphi, -sphi); +Point Point::CoordTransToEllipse(const Point& center, double cphi, double sphi) const +{ + Point p = Point(_x, _y); + return (p - center).Rotate(cphi, -sphi); } /* -This is the reverse funktion of CoordTransToEllipse(), +This is the reverse funktion of CoordTransToEllipse(), where the coord. of a point are transformated to cart. coord. input: - (x,y) : coordinates of the point P in S_2 - (xc,yc) : coordinate of the center in the S_1 (Center of Ellipse) - phi : angle between the S_1 and S_2 - + output: + (xnew,ynew) : new coordinate of the point P in the coord. sys S_1 @@ -184,9 +198,10 @@ where the coord. of a point are transformated to cart. coord. */ -Point Point::CoordTransToCart(const Point& center, double cphi, double sphi) const { - Point p = Point(_x, _y); - return (p.Rotate(cphi, sphi) + center); +Point Point::CoordTransToCart(const Point& center, double cphi, double sphi) const +{ + Point p = Point(_x, _y); + return (p.Rotate(cphi, sphi) + center); } /*rotate a two-dimensional vector by an angle of theta @@ -195,49 +210,55 @@ Rotation-matrix=[cos(theta) -sin(theta)] [ sin(theta) cos(theta)] */ -Point Point::Rotate(double ctheta, double stheta) const { - return Point(_x * ctheta - _y*stheta, _x * stheta + _y * ctheta); +Point Point::Rotate(double ctheta, double stheta) const +{ + return Point(_x * ctheta - _y*stheta, _x * stheta + _y * ctheta); } // sum -const Point Point::operator+(const Point& p) const { - //return Point(_x + p.GetX(), _y + p.GetY()); - return Point(_x + p._x, _y + p._y); +const Point Point::operator+(const Point& p) const +{ + //return Point(_x + p.GetX(), _y + p.GetY()); + return Point(_x + p._x, _y + p._y); } // sub -const Point Point::operator-(const Point& p) const { - // return Point(_x - p.GetX(), _y - p.GetY()); - return Point(_x - p._x, _y - p._y); +const Point Point::operator-(const Point& p) const +{ + // return Point(_x - p.GetX(), _y - p.GetY()); + return Point(_x - p._x, _y - p._y); } // equal -bool Point::operator==(const Point& p) const { +bool Point::operator==(const Point& p) const +{ // return (fabs(_x - p.GetX()) < J_EPS && fabs(_y - p.GetY()) < J_EPS); - return (fabs(_x - p._x) < J_EPS && fabs(_y - p._y) < J_EPS); + return (fabs(_x - p._x) < J_EPS && fabs(_y - p._y) < J_EPS); } // not equal -bool Point::operator!=(const Point& p) const { - //return (fabs(_x - p.GetX()) > J_EPS || fabs(_y - p.GetY()) > J_EPS); - return (fabs(_x - p._x) > J_EPS || fabs(_y - p._y) > J_EPS); +bool Point::operator!=(const Point& p) const +{ + //return (fabs(_x - p.GetX()) > J_EPS || fabs(_y - p.GetY()) > J_EPS); + return (fabs(_x - p._x) > J_EPS || fabs(_y - p._y) > J_EPS); } // multiplication with scalar -const Point operator*(const Point& p, double f) { - //return Point(p.GetX() * f, p.GetY() * f); - return Point(p._x * f, p._y * f); +const Point operator*(const Point& p, double f) +{ + //return Point(p.GetX() * f, p.GetY() * f); + return Point(p._x * f, p._y * f); } // divition with scalar -const Point operator/(const Point& p, double f) { - if (f>J_EPS*J_EPS) - return Point(p._x / f, p._y / f); - else - { - std::cout << "Warning: Point::/operator. dividand "<<f<< " is to small. Set it to 1 instead"<<std::endl; - return Point(p._x, p._y); - } - //return Point(p.GetX() / f, p.GetY() / f); +const Point operator/(const Point& p, double f) +{ + if (f>J_EPS*J_EPS) + return Point(p._x / f, p._y / f); + else { + std::cout << "Warning: Point::/operator. dividand "<<f<< " is to small. Set it to 1 instead"<<std::endl; + return Point(p._x, p._y); + } + //return Point(p.GetX() / f, p.GetY() / f); } diff --git a/geometry/Point.h b/geometry/Point.h index d3ee34ce10c9d06e87efe024193810d401ce63bc..2f5dcca83d3b8e9218f2ac7560d59dc1f2754aa2 100644 --- a/geometry/Point.h +++ b/geometry/Point.h @@ -30,68 +30,68 @@ #include <string> class Point { - public: - double _x; - double _y; - - public: - // constructors - Point(); - Point(double x, double y); - Point(const Point& orig); - - - /** - * Set/Get the x component - */ - void SetX(double x); - - /** - * Set/Get the y component - */ - void SetY(double y); - - - /** - * Set/Get the x component - */ - double GetX() const; - - /** - * Set/Get the y component - */ - double GetY() const; - - /// Norm - double Norm() const; - /// Norm square - double NormSquare() const; - /// normalized vector - Point Normalized() const; - /// dot product - double ScalarP(const Point& v) const; - /// determinant of the square matrix formed by the vectors [ this, v] - double Det(const Point& v) const; - /// translation and rotation in Ellipse coordinate system - Point CoordTransToEllipse(const Point& center, double cphi, double sphi) const; - /// translation and rotation in cartesian system - Point CoordTransToCart(const Point& center, double cphi, double sphi) const; - /// rotate the vector by theta - Point Rotate(double ctheta, double stheta) const; - - - // operators - /// addition - const Point operator+(const Point& p) const; - /// substraction - const Point operator-(const Point& p) const; - /// equal - bool operator==(const Point& p) const; - /// not equal - bool operator!=(const Point& p) const; - - /// nice formating of the point - std::string toString() const; +public: + double _x; + double _y; + +public: + // constructors + Point(); + Point(double x, double y); + Point(const Point& orig); + + + /** + * Set/Get the x component + */ + void SetX(double x); + + /** + * Set/Get the y component + */ + void SetY(double y); + + + /** + * Set/Get the x component + */ + double GetX() const; + + /** + * Set/Get the y component + */ + double GetY() const; + + /// Norm + double Norm() const; + /// Norm square + double NormSquare() const; + /// normalized vector + Point Normalized() const; + /// dot product + double ScalarP(const Point& v) const; + /// determinant of the square matrix formed by the vectors [ this, v] + double Det(const Point& v) const; + /// translation and rotation in Ellipse coordinate system + Point CoordTransToEllipse(const Point& center, double cphi, double sphi) const; + /// translation and rotation in cartesian system + Point CoordTransToCart(const Point& center, double cphi, double sphi) const; + /// rotate the vector by theta + Point Rotate(double ctheta, double stheta) const; + + + // operators + /// addition + const Point operator+(const Point& p) const; + /// substraction + const Point operator-(const Point& p) const; + /// equal + bool operator==(const Point& p) const; + /// not equal + bool operator!=(const Point& p) const; + + /// nice formating of the point + std::string toString() const; }; /// multiplication diff --git a/geometry/Room.cpp b/geometry/Room.cpp index 1f9fa66b8cbf492a4de225700084c3e78e198c7a..fc9718bcd75513514e3dd40920003386d8cf0bf7 100644 --- a/geometry/Room.cpp +++ b/geometry/Room.cpp @@ -1,6 +1,6 @@ /** * File: Room.cpp - * + * * Created on 30. September 2010, 11:58 * @section LICENSE * This file is part of JuPedSim. @@ -34,108 +34,124 @@ using namespace std; Konstruktoren ************************************************************/ -Room::Room() { - _id = -1; - _state=ROOM_CLEAN; //smoke-free - _caption = "no room caption"; - _zPos = -1.0; - _subRooms = vector<SubRoom* > (); - _outputFile=NULL; +Room::Room() +{ + _id = -1; + _state=ROOM_CLEAN; //smoke-free + _caption = "no room caption"; + _zPos = -1.0; + _subRooms = vector<SubRoom* > (); + _outputFile=NULL; } -Room::Room(const Room& orig) { - _id = orig.GetID(); - _caption = orig.GetCaption(); - _zPos = orig.GetZPos(); - _subRooms = orig.GetAllSubRooms(); - _state=orig.GetState(); - _outputFile=orig.GetOutputHandler(); +Room::Room(const Room& orig) +{ + _id = orig.GetID(); + _caption = orig.GetCaption(); + _zPos = orig.GetZPos(); + _subRooms = orig.GetAllSubRooms(); + _state=orig.GetState(); + _outputFile=orig.GetOutputHandler(); } -Room::~Room() { - for (unsigned int i = 0; i < _subRooms.size(); i++) - delete _subRooms[i]; +Room::~Room() +{ + for (unsigned int i = 0; i < _subRooms.size(); i++) + delete _subRooms[i]; } /************************************************************* Setter-Funktionen ************************************************************/ -void Room::SetID(int ID) { - _id = ID; +void Room::SetID(int ID) +{ + _id = ID; } -void Room::SetCaption(string s) { - _caption = s; +void Room::SetCaption(string s) +{ + _caption = s; } -void Room::SetZPos(double z) { - _zPos = z; +void Room::SetZPos(double z) +{ + _zPos = z; } -void Room::SetSubRoom(SubRoom* subroom, int index) { - if ((index >= 0) && (index < GetNumberOfSubRooms())) { - _subRooms[index] = subroom; - } else { - Log->Write("ERROR: Wrong Index in Room::SetSubRoom()"); - exit(0); - } +void Room::SetSubRoom(SubRoom* subroom, int index) +{ + if ((index >= 0) && (index < GetNumberOfSubRooms())) { + _subRooms[index] = subroom; + } else { + Log->Write("ERROR: Wrong Index in Room::SetSubRoom()"); + exit(0); + } } -void Room::SetState(RoomState state) { - _state=state; +void Room::SetState(RoomState state) +{ + _state=state; } /************************************************************* Getter-Functions ************************************************************/ -int Room::GetID() const { - return _id; +int Room::GetID() const +{ + return _id; } -string Room::GetCaption() const { - return _caption; +string Room::GetCaption() const +{ + return _caption; } -double Room::GetZPos() const { - //if(pCaption=="070") return pZPos+1.0; - return _zPos; +double Room::GetZPos() const +{ + //if(pCaption=="070") return pZPos+1.0; + return _zPos; } -int Room::GetNumberOfSubRooms() const { - return _subRooms.size(); +int Room::GetNumberOfSubRooms() const +{ + return _subRooms.size(); } -const vector<SubRoom*>& Room::GetAllSubRooms() const { - return _subRooms; +const vector<SubRoom*>& Room::GetAllSubRooms() const +{ + return _subRooms; } -SubRoom* Room::GetSubRoom(int index) const { - if ((index >= 0) && (index < (int) _subRooms.size())) - return _subRooms[index]; - else { - char tmp[CLENGTH]; - sprintf(tmp,"ERROR: Room::GetSubRoom() Wrong subroom index [%d] for room index [%d] ",index,_id); - Log->Write(tmp); - exit(EXIT_FAILURE); - } +SubRoom* Room::GetSubRoom(int index) const +{ + if ((index >= 0) && (index < (int) _subRooms.size())) + return _subRooms[index]; + else { + char tmp[CLENGTH]; + sprintf(tmp,"ERROR: Room::GetSubRoom() Wrong subroom index [%d] for room index [%d] ",index,_id); + Log->Write(tmp); + exit(EXIT_FAILURE); + } } #ifdef _SIMULATOR -int Room::GetNumberOfPedestrians() const { - int sum = 0; - for (int i = 0; i < GetNumberOfSubRooms(); i++) { - sum += GetSubRoom(i)->GetNumberOfPedestrians(); - } - return sum; +int Room::GetNumberOfPedestrians() const +{ + int sum = 0; + for (int i = 0; i < GetNumberOfSubRooms(); i++) { + sum += GetSubRoom(i)->GetNumberOfPedestrians(); + } + return sum; } #endif // _SIMULATOR -RoomState Room::GetState() const { - return _state; +RoomState Room::GetState() const +{ + return _state; } @@ -143,17 +159,19 @@ RoomState Room::GetState() const { /************************************************************* Sonstige Funktionen ************************************************************/ -void Room::AddSubRoom(SubRoom* r) { - _subRooms.push_back(r); +void Room::AddSubRoom(SubRoom* r) +{ + _subRooms.push_back(r); } -void Room::DeleteSubRoom(int index) { - if ((index >= 0) && (index < (int) _subRooms.size())) - _subRooms.erase(_subRooms.begin() + index); - else { - Log->Write("ERROR: Wrong Index in Room::DeleteSubRoom()"); - exit(0); - } +void Room::DeleteSubRoom(int index) +{ + if ((index >= 0) && (index < (int) _subRooms.size())) + _subRooms.erase(_subRooms.begin() + index); + else { + Log->Write("ERROR: Wrong Index in Room::DeleteSubRoom()"); + exit(0); + } } /************************************************************* @@ -161,32 +179,37 @@ void Room::DeleteSubRoom(int index) { ************************************************************/ -void Room::WriteToErrorLog() const { - char tmp[CLENGTH]; - string s; - sprintf(tmp, "\tRaum: %d [%s]:\n", _id, _caption.c_str()); - s.append(tmp); - Log->Write(s); - // SubRooms - for (int i = 0; i < GetNumberOfSubRooms(); i++) { - SubRoom* s = GetSubRoom(i); - s->WriteToErrorLog(); - } +void Room::WriteToErrorLog() const +{ + char tmp[CLENGTH]; + string s; + sprintf(tmp, "\tRaum: %d [%s]:\n", _id, _caption.c_str()); + s.append(tmp); + Log->Write(s); + // SubRooms + for (int i = 0; i < GetNumberOfSubRooms(); i++) { + SubRoom* s = GetSubRoom(i); + s->WriteToErrorLog(); + } } -const vector<int>& Room::GetAllTransitionsIDs() const { - return _transitionsIDs; +const vector<int>& Room::GetAllTransitionsIDs() const +{ + return _transitionsIDs; } -void Room::AddTransitionID(int ID){ - _transitionsIDs.push_back(ID); +void Room::AddTransitionID(int ID) +{ + _transitionsIDs.push_back(ID); } -void Room::SetOutputHandler(OutputHandler* oh){ - _outputFile=oh; +void Room::SetOutputHandler(OutputHandler* oh) +{ + _outputFile=oh; } -OutputHandler* Room::GetOutputHandler() const { - return _outputFile; +OutputHandler* Room::GetOutputHandler() const +{ + return _outputFile; } diff --git a/geometry/Room.h b/geometry/Room.h index 19a038113beea115db2d06ef3a8e08655fd44f0b..5242ac3576eda8cec13edf97507949a86d7ab67e 100644 --- a/geometry/Room.h +++ b/geometry/Room.h @@ -33,129 +33,129 @@ //class SubRoom; class Room { - private: - - /// room ID and index - int _id; - /// room state - RoomState _state; - /// room caption - std::string _caption; - /// room elevation - double _zPos; - /// all subrooms/partitions of the room - std::vector<SubRoom*> _subRooms; - /// all transitions ids - std::vector<int> _transitionsIDs; - /// needed if the trajectories for this room are to be write in a special way - OutputHandler* _outputFile; - - public: - Room(); - Room(const Room& orig); - virtual ~Room(); - - - /** - * Set/Get the id of the room which is also used as index - */ - void SetID(int ID); - - /** - * Set/Get the caption of the room - */ - void SetCaption(std::string s); - - /** - * Set/Get the elevation of the room - */ - void SetZPos(double z); - - /** - * Add a SubRoom at the given index - */ - void SetSubRoom(SubRoom* subroom, int index); - - /** - * Set/Get the state of the room as defined in the macro.h file - */ - void SetState(RoomState state); - - /** - * Set/Get the id of the room which is also used as index - */ - int GetID() const; - - /** - * Set/Get the caption of the room - */ - std::string GetCaption() const; - - /** - * Set/Get the elevation of the room - */ - double GetZPos() const; - - /** - * @return the number of subrooms - */ - int GetNumberOfSubRooms() const; - - /** - * @return a vector containing all subrooms - */ - const std::vector<SubRoom*>& GetAllSubRooms() const; - - /** - * @return a vector containing all transitions Ids - */ - const std::vector<int>& GetAllTransitionsIDs() const; - - /** - * @return the Subroom with the corresponding index - */ - SubRoom* GetSubRoom(int index) const; - - /** - * @return the number of pedestrians in the rooms (all subrooms) - */ - int GetNumberOfPedestrians() const; - - /** - * @return the state for this room - */ - RoomState GetState()const; - - /** - * Push a new subroom in the vector - */ - void AddSubRoom(SubRoom* r); - - /** - * Delete the subroom at the specified index - */ - void DeleteSubRoom(int index); - - /** - * Add a new transition id - */ - void AddTransitionID(int ID); - - - /** - * Debug output for this class - */ - void WriteToErrorLog() const; - - /** - * Used by MPI in the case each room should be written in a specific file - */ - void SetOutputHandler(OutputHandler* oh); - - /** - * Used by MPI in the case each room should be written in a specific file - */ - OutputHandler* GetOutputHandler() const; +private: + + /// room ID and index + int _id; + /// room state + RoomState _state; + /// room caption + std::string _caption; + /// room elevation + double _zPos; + /// all subrooms/partitions of the room + std::vector<SubRoom*> _subRooms; + /// all transitions ids + std::vector<int> _transitionsIDs; + /// needed if the trajectories for this room are to be write in a special way + OutputHandler* _outputFile; + +public: + Room(); + Room(const Room& orig); + virtual ~Room(); + + + /** + * Set/Get the id of the room which is also used as index + */ + void SetID(int ID); + + /** + * Set/Get the caption of the room + */ + void SetCaption(std::string s); + + /** + * Set/Get the elevation of the room + */ + void SetZPos(double z); + + /** + * Add a SubRoom at the given index + */ + void SetSubRoom(SubRoom* subroom, int index); + + /** + * Set/Get the state of the room as defined in the macro.h file + */ + void SetState(RoomState state); + + /** + * Set/Get the id of the room which is also used as index + */ + int GetID() const; + + /** + * Set/Get the caption of the room + */ + std::string GetCaption() const; + + /** + * Set/Get the elevation of the room + */ + double GetZPos() const; + + /** + * @return the number of subrooms + */ + int GetNumberOfSubRooms() const; + + /** + * @return a vector containing all subrooms + */ + const std::vector<SubRoom*>& GetAllSubRooms() const; + + /** + * @return a vector containing all transitions Ids + */ + const std::vector<int>& GetAllTransitionsIDs() const; + + /** + * @return the Subroom with the corresponding index + */ + SubRoom* GetSubRoom(int index) const; + + /** + * @return the number of pedestrians in the rooms (all subrooms) + */ + int GetNumberOfPedestrians() const; + + /** + * @return the state for this room + */ + RoomState GetState()const; + + /** + * Push a new subroom in the vector + */ + void AddSubRoom(SubRoom* r); + + /** + * Delete the subroom at the specified index + */ + void DeleteSubRoom(int index); + + /** + * Add a new transition id + */ + void AddTransitionID(int ID); + + + /** + * Debug output for this class + */ + void WriteToErrorLog() const; + + /** + * Used by MPI in the case each room should be written in a specific file + */ + void SetOutputHandler(OutputHandler* oh); + + /** + * Used by MPI in the case each room should be written in a specific file + */ + OutputHandler* GetOutputHandler() const; }; diff --git a/geometry/SubRoom.cpp b/geometry/SubRoom.cpp index e7196269ba5613ea26d77f231e94a829e17ec2c2..fd3c6880d54a507a4aff2aff76e3bfda7c42c1b1 100644 --- a/geometry/SubRoom.cpp +++ b/geometry/SubRoom.cpp @@ -46,599 +46,642 @@ using namespace std; int SubRoom::_static_uid=0; -SubRoom::SubRoom() { - _id = -1; - _roomID=-1; - _walls = vector<Wall > (); - _poly = vector<Point > (); - _obstacles=vector<Obstacle*> (); - - _crossings = vector<Crossing*>(); - _transitions = vector<Transition*>(); - _hlines = vector<Hline*>(); - - _planeEquation[0]=0.0; - _planeEquation[1]=0.0; - _planeEquation[2]=0.0; - _cosAngleWithHorizontalPlane=0; - - _goalIDs = vector<int> (); - _area = 0.0; - _closed=false; - _uid = _static_uid++; +SubRoom::SubRoom() +{ + _id = -1; + _roomID=-1; + _walls = vector<Wall > (); + _poly = vector<Point > (); + _obstacles=vector<Obstacle*> (); + + _crossings = vector<Crossing*>(); + _transitions = vector<Transition*>(); + _hlines = vector<Hline*>(); + + _planeEquation[0]=0.0; + _planeEquation[1]=0.0; + _planeEquation[2]=0.0; + _cosAngleWithHorizontalPlane=0; + + _goalIDs = vector<int> (); + _area = 0.0; + _closed=false; + _uid = _static_uid++; #ifdef _SIMULATOR - _peds = vector<Pedestrian* > (); + _peds = vector<Pedestrian* > (); #endif //_SIMULATOR } -SubRoom::SubRoom(const SubRoom& orig) { - _id = orig.GetSubRoomID(); - _walls = orig.GetAllWalls(); - _poly = orig.GetPolygon(); - _goalIDs = orig.GetAllGoalIDs(); - _area = orig.GetArea(); - _closed=orig.GetClosed(); - _roomID=orig.GetRoomID(); - _uid = orig.GetUID(); - _cosAngleWithHorizontalPlane=orig.GetCosAngleWithHorizontal(); +SubRoom::SubRoom(const SubRoom& orig) +{ + _id = orig.GetSubRoomID(); + _walls = orig.GetAllWalls(); + _poly = orig.GetPolygon(); + _goalIDs = orig.GetAllGoalIDs(); + _area = orig.GetArea(); + _closed=orig.GetClosed(); + _roomID=orig.GetRoomID(); + _uid = orig.GetUID(); + _cosAngleWithHorizontalPlane=orig.GetCosAngleWithHorizontal(); #ifdef _SIMULATOR - _peds = orig.GetAllPedestrians(); + _peds = orig.GetAllPedestrians(); #endif //_SIMULATOR } -SubRoom::~SubRoom() { - if (_walls.size() > 0) _walls.clear(); - if (_poly.size() > 0) _poly.clear(); - for (unsigned int i = 0; i < _obstacles.size(); i++) { - delete _obstacles[i]; - } - _obstacles.clear(); +SubRoom::~SubRoom() +{ + if (_walls.size() > 0) _walls.clear(); + if (_poly.size() > 0) _poly.clear(); + for (unsigned int i = 0; i < _obstacles.size(); i++) { + delete _obstacles[i]; + } + _obstacles.clear(); #ifdef _SIMULATOR - for (unsigned int i = 0; i < _peds.size(); i++) { - delete _peds[i]; - } + for (unsigned int i = 0; i < _peds.size(); i++) { + delete _peds[i]; + } #endif //_SIMULATOR } // Setter -Funktionen -void SubRoom::SetSubRoomID(int ID) { - _id = ID; +void SubRoom::SetSubRoomID(int ID) +{ + _id = ID; } -void SubRoom::SetClosed(double closed) { - _closed = closed; +void SubRoom::SetClosed(double closed) +{ + _closed = closed; } -void SubRoom::SetRoomID(int ID) { - _roomID = ID; +void SubRoom::SetRoomID(int ID) +{ + _roomID = ID; } -int SubRoom::GetSubRoomID() const { - return _id; +int SubRoom::GetSubRoomID() const +{ + return _id; } -double SubRoom::GetClosed() const { - return _closed; +double SubRoom::GetClosed() const +{ + return _closed; } // unique identifier for this subroom -int SubRoom::GetUID() const { - return _uid; - //return pRoomID * 1000 + pID; +int SubRoom::GetUID() const +{ + return _uid; + //return pRoomID * 1000 + pID; } -double SubRoom::GetArea() const { - return _area; +double SubRoom::GetArea() const +{ + return _area; } -int SubRoom::GetRoomID() const { - return _roomID; +int SubRoom::GetRoomID() const +{ + return _roomID; } -int SubRoom::GetNumberOfWalls() const { - return _walls.size(); +int SubRoom::GetNumberOfWalls() const +{ + return _walls.size(); } -const vector<Wall>& SubRoom::GetAllWalls() const { - return _walls; +const vector<Wall>& SubRoom::GetAllWalls() const +{ + return _walls; } -const Wall& SubRoom::GetWall(int index) const { - if ((index >= 0) && (index < GetNumberOfWalls())) - return _walls[index]; - else { - Log->Write("ERROR: Wrong 'index' in SubRoom::GetWall()"); - exit(0); - } +const Wall& SubRoom::GetWall(int index) const +{ + if ((index >= 0) && (index < GetNumberOfWalls())) + return _walls[index]; + else { + Log->Write("ERROR: Wrong 'index' in SubRoom::GetWall()"); + exit(0); + } } -const vector<Point>& SubRoom::GetPolygon() const { - return _poly; +const vector<Point>& SubRoom::GetPolygon() const +{ + return _poly; } -const vector<Obstacle*>& SubRoom::GetAllObstacles() const { - return _obstacles; +const vector<Obstacle*>& SubRoom::GetAllObstacles() const +{ + return _obstacles; } -int SubRoom::GetNumberOfGoalIDs() const { - return _goalIDs.size(); +int SubRoom::GetNumberOfGoalIDs() const +{ + return _goalIDs.size(); } -const vector<int>& SubRoom::GetAllGoalIDs() const { - return _goalIDs; +const vector<int>& SubRoom::GetAllGoalIDs() const +{ + return _goalIDs; } // Sonstiges -void SubRoom::AddWall(const Wall& w) { - _walls.push_back(w); +void SubRoom::AddWall(const Wall& w) +{ + _walls.push_back(w); } -void SubRoom::AddObstacle(Obstacle* obs){ - _obstacles.push_back(obs); - CheckObstacles(); +void SubRoom::AddObstacle(Obstacle* obs) +{ + _obstacles.push_back(obs); + CheckObstacles(); } -void SubRoom::AddGoalID(int ID) { - _goalIDs.push_back(ID); +void SubRoom::AddGoalID(int ID) +{ + _goalIDs.push_back(ID); } -void SubRoom::AddCrossing(Crossing* line){ - _crossings.push_back(line); - _goalIDs.push_back(line->GetUniqueID()); +void SubRoom::AddCrossing(Crossing* line) +{ + _crossings.push_back(line); + _goalIDs.push_back(line->GetUniqueID()); } -void SubRoom::AddTransition(Transition* line){ - _transitions.push_back(line); - _goalIDs.push_back(line->GetUniqueID()); +void SubRoom::AddTransition(Transition* line) +{ + _transitions.push_back(line); + _goalIDs.push_back(line->GetUniqueID()); } -void SubRoom::AddHline(Hline* line){ - _hlines.push_back(line); - _goalIDs.push_back(line->GetUniqueID()); +void SubRoom::AddHline(Hline* line) +{ + _hlines.push_back(line); + _goalIDs.push_back(line->GetUniqueID()); } -const vector<Crossing*>& SubRoom::GetAllCrossings() const{ - return _crossings; +const vector<Crossing*>& SubRoom::GetAllCrossings() const +{ + return _crossings; } -const vector<Transition*>& SubRoom::GetAllTransitions() const{ - return _transitions; +const vector<Transition*>& SubRoom::GetAllTransitions() const +{ + return _transitions; } -const vector<Hline*>& SubRoom::GetAllHlines() const{ - return _hlines; +const vector<Hline*>& SubRoom::GetAllHlines() const +{ + return _hlines; } -const Crossing* SubRoom::GetCrossing(int i) const { - return _crossings[i]; +const Crossing* SubRoom::GetCrossing(int i) const +{ + return _crossings[i]; } -const Transition* SubRoom::GetTransition(int i) const { - return _transitions[i]; +const Transition* SubRoom::GetTransition(int i) const +{ + return _transitions[i]; } -const Hline* SubRoom::GetHline(int i) const { - return _hlines[i]; +const Hline* SubRoom::GetHline(int i) const +{ + return _hlines[i]; } -void SubRoom::RemoveGoalID(int ID){ - for (unsigned int i=0;i<_goalIDs.size();i++){ - if(_goalIDs[i]==ID){ - Log->Write("Removing goal"); - _goalIDs.erase(_goalIDs.begin()+i); - return; - } - } - Log->Write("There is no goal with that id to remove"); +void SubRoom::RemoveGoalID(int ID) +{ + for (unsigned int i=0; i<_goalIDs.size(); i++) { + if(_goalIDs[i]==ID) { + Log->Write("Removing goal"); + _goalIDs.erase(_goalIDs.begin()+i); + return; + } + } + Log->Write("There is no goal with that id to remove"); } -void SubRoom::CalculateArea() { - double sum = 0; - int n = (int) _poly.size(); - for (int i = 0; i < n; i++) { - sum += (_poly[i].GetY() + _poly[(i + 1) % n].GetY())*(_poly[i].GetX() - _poly[(i + 1) % n].GetX()); - } - _area=(0.5 * fabs(sum)); +void SubRoom::CalculateArea() +{ + double sum = 0; + int n = (int) _poly.size(); + for (int i = 0; i < n; i++) { + sum += (_poly[i].GetY() + _poly[(i + 1) % n].GetY())*(_poly[i].GetX() - _poly[(i + 1) % n].GetX()); + } + _area=(0.5 * fabs(sum)); } -Point SubRoom::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.0*signedArea); - py /= (6.0*signedArea); +Point SubRoom::GetCentroid() const +{ - return Point(px,py); + 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.0*signedArea); + py /= (6.0*signedArea); + + return Point(px,py); } bool SubRoom::IsVisible(const Point& p1, const Point& p2, bool considerHlines) { - // generate certain connection lines - // connecting p1 with p2 - Line cl = Line(p1,p2); - bool temp = true; - //check intersection with Walls - for(unsigned int i = 0; i < _walls.size(); i++) { - if(temp && cl.IntersectionWith(_walls[i])) - temp = false; - } + // generate certain connection lines + // connecting p1 with p2 + Line cl = Line(p1,p2); + bool temp = true; + //check intersection with Walls + for(unsigned int i = 0; i < _walls.size(); i++) { + if(temp && cl.IntersectionWith(_walls[i])) + temp = false; + } + + + //check intersection with obstacles + for(unsigned int i = 0; i < _obstacles.size(); i++) { + Obstacle * obs = _obstacles[i]; + for(unsigned int k = 0; k<obs->GetAllWalls().size(); k++) { + const Wall& w = obs->GetAllWalls()[k]; + if(temp && cl.IntersectionWith(w)) + temp = false; + } + } + + + // check intersection with other hlines in room + if(considerHlines) + for(unsigned int i = 0; i < _hlines.size(); i++) { + if(_hlines[i]->IsInLineSegment(p1)|| _hlines[i]->IsInLineSegment(p2)) continue; + if(temp && cl.IntersectionWith(*(Line*)_hlines[i])) + temp = false; + } + + return temp; +} +bool SubRoom::IsVisible(Line* l1, Line* l2, bool considerHlines) +{ + // generate certain connection lines + // connecting p1 mit p1, p1 mit p2, p2 mit p1, p2 mit p2 und center mit center + Line cl[5]; + cl[0] = Line(l1->GetPoint1(), l2->GetPoint1()); + cl[1] = Line(l1->GetPoint1(), l2->GetPoint2()); + cl[2] = Line(l1->GetPoint2(), l2->GetPoint1()); + cl[3] = Line(l1->GetPoint2(), l2->GetPoint2()); + cl[4] = Line(l1->GetCentre(), l2->GetCentre()); + bool temp[5] = {true, true, true, true, true}; + //check intersection with Walls + for(unsigned int i = 0; i < GetAllWalls().size(); i++) { + for(int k = 0; k < 5; k++) { + if(temp[k] && cl[k].IntersectionWith(_walls[i]) && (cl[k].NormalVec() != _walls[i].NormalVec() || l1->NormalVec() != l2->NormalVec())) + temp[k] = false; + } + } + + //check intersection with obstacles + for(unsigned int i = 0; i < GetAllObstacles().size(); i++) { + Obstacle * obs = GetAllObstacles()[i]; + for(unsigned int k = 0; k<obs->GetAllWalls().size(); k++) { + const Wall& w = obs->GetAllWalls()[k]; + if((w.operator !=(*l1)) && (w.operator !=(*l2))) + for(int j = 0; j < 5; j++) { + if(temp[j] && cl[j].IntersectionWith(w)) + temp[j] = false; + } + } + } + + // check intersection with other hlines in room + if(considerHlines) + for(unsigned int i = 0; i < _hlines.size(); i++) { + if ( (l1->operator !=(*(Line*)_hlines[i])) && (l2->operator !=(*(Line*)_hlines[i])) ) { + for(int k = 0; k < 5; k++) { + if(temp[k] && cl[k].IntersectionWith(*(Line*)_hlines[i])) + temp[k] = false; + } + } + } + return temp[0] || temp[1] || temp[2] || temp[3] || temp[4]; +} - //check intersection with obstacles - for(unsigned int i = 0; i < _obstacles.size(); i++) { - Obstacle * obs = _obstacles[i]; - for(unsigned int k = 0; k<obs->GetAllWalls().size(); k++){ - const Wall& w = obs->GetAllWalls()[k]; - if(temp && cl.IntersectionWith(w)) - temp = false; - } - } - // check intersection with other hlines in room - if(considerHlines) - for(unsigned int i = 0; i < _hlines.size(); i++) { - if(_hlines[i]->IsInLineSegment(p1)|| _hlines[i]->IsInLineSegment(p2)) continue; - if(temp && cl.IntersectionWith(*(Line*)_hlines[i])) - temp = false; - } - return temp; +// this is the case if they share a transition or crossing +bool SubRoom::IsDirectlyConnectedWith(const SubRoom* sub) const +{ + + //check the crossings + const vector<Crossing*>& crossings = sub->GetAllCrossings(); + for (unsigned int i = 0; i < crossings.size(); i++) { + for (unsigned int j = 0; j < _crossings.size(); j++) { + int uid1 = crossings[i]->GetUniqueID(); + int uid2 = _crossings[j]->GetUniqueID(); + // ignore my transition + if (uid1 == uid2) + return true; + } + } + + // and finally the transitions + const vector<Transition*>& transitions = sub->GetAllTransitions(); + for (unsigned int i = 0; i < transitions.size(); i++) { + for (unsigned int j = 0; j < _transitions.size(); j++) { + int uid1 = transitions[i]->GetUniqueID(); + int uid2 = _transitions[j]->GetUniqueID(); + // ignore my transition + if (uid1 == uid2) + return true; + } + } + + return false; +} + +void SubRoom::SetPlanEquation(double A, double B, double C) +{ + _planeEquation[0]=A; + _planeEquation[1]=B; + _planeEquation[2]=C; + //compute and cache the cosine of angle with the plane z=h + _cosAngleWithHorizontalPlane= (1.0/sqrt(A*A+B*B+1)); } -bool SubRoom::IsVisible(Line* l1, Line* l2, bool considerHlines) +const double* SubRoom::GetPlanEquation() const { - // generate certain connection lines - // connecting p1 mit p1, p1 mit p2, p2 mit p1, p2 mit p2 und center mit center - Line cl[5]; - cl[0] = Line(l1->GetPoint1(), l2->GetPoint1()); - cl[1] = Line(l1->GetPoint1(), l2->GetPoint2()); - cl[2] = Line(l1->GetPoint2(), l2->GetPoint1()); - cl[3] = Line(l1->GetPoint2(), l2->GetPoint2()); - cl[4] = Line(l1->GetCentre(), l2->GetCentre()); - bool temp[5] = {true, true, true, true, true}; - //check intersection with Walls - for(unsigned int i = 0; i < GetAllWalls().size(); i++) { - for(int k = 0; k < 5; k++) { - if(temp[k] && cl[k].IntersectionWith(_walls[i]) && (cl[k].NormalVec() != _walls[i].NormalVec() || l1->NormalVec() != l2->NormalVec())) - temp[k] = false; - } - } - - //check intersection with obstacles - for(unsigned int i = 0; i < GetAllObstacles().size(); i++) { - Obstacle * obs = GetAllObstacles()[i]; - for(unsigned int k = 0; k<obs->GetAllWalls().size(); k++){ - const Wall& w = obs->GetAllWalls()[k]; - if((w.operator !=(*l1)) && (w.operator !=(*l2))) - for(int j = 0; j < 5; j++) { - if(temp[j] && cl[j].IntersectionWith(w)) - temp[j] = false; - } - } - } - - // check intersection with other hlines in room - if(considerHlines) - for(unsigned int i = 0; i < _hlines.size(); i++) { - if ( (l1->operator !=(*(Line*)_hlines[i])) && (l2->operator !=(*(Line*)_hlines[i])) ) { - for(int k = 0; k < 5; k++) { - if(temp[k] && cl[k].IntersectionWith(*(Line*)_hlines[i])) - temp[k] = false; - } - } - } - return temp[0] || temp[1] || temp[2] || temp[3] || temp[4]; + return _planeEquation; } +double SubRoom::GetElevation(const Point& p) const +{ + return _planeEquation[0] * p._x + _planeEquation[1] * p._y + _planeEquation[2]; +} +double SubRoom::GetCosAngleWithHorizontal() const +{ + return _cosAngleWithHorizontalPlane; +} -// this is the case if they share a transition or crossing -bool SubRoom::IsDirectlyConnectedWith(const SubRoom* sub) const { - - //check the crossings - const vector<Crossing*>& crossings = sub->GetAllCrossings(); - for (unsigned int i = 0; i < crossings.size(); i++) { - for (unsigned int j = 0; j < _crossings.size(); j++) { - int uid1 = crossings[i]->GetUniqueID(); - int uid2 = _crossings[j]->GetUniqueID(); - // ignore my transition - if (uid1 == uid2) - return true; - } - } - - // and finally the transitions - const vector<Transition*>& transitions = sub->GetAllTransitions(); - for (unsigned int i = 0; i < transitions.size(); i++) { - for (unsigned int j = 0; j < _transitions.size(); j++) { - int uid1 = transitions[i]->GetUniqueID(); - int uid2 = _transitions[j]->GetUniqueID(); - // ignore my transition - if (uid1 == uid2) - return true; - } - } - - return false; -} - -void SubRoom::SetPlanEquation(double A, double B, double C) { - _planeEquation[0]=A; - _planeEquation[1]=B; - _planeEquation[2]=C; - //compute and cache the cosine of angle with the plane z=h - _cosAngleWithHorizontalPlane= (1.0/sqrt(A*A+B*B+1)); -} - -const double* SubRoom::GetPlanEquation() const { - return _planeEquation; -} - -double SubRoom::GetElevation(const Point& p) const { - return _planeEquation[0] * p._x + _planeEquation[1] * p._y + _planeEquation[2]; -} - -double SubRoom::GetCosAngleWithHorizontal() const { - return _cosAngleWithHorizontalPlane; - -} - -void SubRoom::CheckObstacles(){ - for(unsigned int i = 0; i<_walls.size();i++){ - for(unsigned int j = 0; j<_obstacles.size();j++){ - if(_obstacles[j]->IntersectWithLine(_walls[i])){ - Log->Write("INFO: \tthe obstacle id [%d] is intersection with subroom [%d]",_obstacles[j]->GetId(),_id); - Log->Write("INFO: \tthe triangulation will not work."); - exit(EXIT_FAILURE); - } - } - } -} - -void SubRoom::SanityCheck(){ - if(_obstacles.size()==0){ - if((IsConvex()==false) && (_hlines.size()==0)){ - Log->Write("WARNING:\t Room [%d] Subroom [%d] is not convex!",_roomID,_id); - Log->Write("\t\t you might consider adding extra hlines in your routing.xml file"); - } else { - // everything is fine - } - } else { - if(_hlines.size()==0){ - Log->Write("WARNING:\t you have obstacles in room [%d] Subroom [%d]!",_roomID,_id); - Log->Write("\t\t you might consider adding extra hlines in your routing.xml file"); - }else { - // everything is fine - } - } +void SubRoom::CheckObstacles() +{ + for(unsigned int i = 0; i<_walls.size(); i++) { + for(unsigned int j = 0; j<_obstacles.size(); j++) { + if(_obstacles[j]->IntersectWithLine(_walls[i])) { + Log->Write("INFO: \tthe obstacle id [%d] is intersection with subroom [%d]",_obstacles[j]->GetId(),_id); + Log->Write("INFO: \tthe triangulation will not work."); + exit(EXIT_FAILURE); + } + } + } +} + +void SubRoom::SanityCheck() +{ + if(_obstacles.size()==0) { + if((IsConvex()==false) && (_hlines.size()==0)) { + Log->Write("WARNING:\t Room [%d] Subroom [%d] is not convex!",_roomID,_id); + Log->Write("\t\t you might consider adding extra hlines in your routing.xml file"); + } else { + // everything is fine + } + } else { + if(_hlines.size()==0) { + Log->Write("WARNING:\t you have obstacles in room [%d] Subroom [%d]!",_roomID,_id); + Log->Write("\t\t you might consider adding extra hlines in your routing.xml file"); + } else { + // everything is fine + } + } } ///http://stackoverflow.com/questions/471962/how-do-determine-if-a-polygon-is-complex-convex-nonconvex -bool SubRoom::IsConvex(){ - unsigned int hsize=_poly.size(); - unsigned int pos=0; - unsigned int neg=0; - - if(hsize==0){ - Log->Write("WARNING:\t cannot check empty polygon for convexification"); - Log->Write("WARNING:\t Did you forget to tall ConvertLineToPoly() ?"); - return false; - } - - for(unsigned int i=0;i<hsize;i++) - { - Point vecAB= _poly[(i+1)%hsize]-_poly[i%hsize]; - Point vecBC= _poly[(i+2)%hsize]-_poly[(i+1)%hsize]; - double det= vecAB.Det(vecBC); - if(fabs(det)<J_EPS) det=0.0; - - if(det<0.0){ - neg++; - } - else if(det>0.0) - { - pos++; - } - else - { - pos++; - neg++; - } - - } - - if ( (pos==hsize ) || (neg==hsize) ) { - return true; - } - return false; +bool SubRoom::IsConvex() +{ + unsigned int hsize=_poly.size(); + unsigned int pos=0; + unsigned int neg=0; + + if(hsize==0) { + Log->Write("WARNING:\t cannot check empty polygon for convexification"); + Log->Write("WARNING:\t Did you forget to tall ConvertLineToPoly() ?"); + return false; + } + + for(unsigned int i=0; i<hsize; i++) { + Point vecAB= _poly[(i+1)%hsize]-_poly[i%hsize]; + Point vecBC= _poly[(i+2)%hsize]-_poly[(i+1)%hsize]; + double det= vecAB.Det(vecBC); + if(fabs(det)<J_EPS) det=0.0; + + if(det<0.0) { + neg++; + } else if(det>0.0) { + pos++; + } else { + pos++; + neg++; + } + + } + + if ( (pos==hsize ) || (neg==hsize) ) { + return true; + } + return false; } ///http://stackoverflow.com/questions/9473570/polygon-vertices-clockwise-or-counterclockwise/ -bool SubRoom::IsClockwise(){ - 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); - } +bool SubRoom::IsClockwise() +{ + 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]; + Point vecAB= _poly[1]-_poly[0]; + Point vecBC= _poly[2]-_poly[1]; - double det=vecAB.Det(vecBC); - if(fabs(det)<J_EPS) det=0.0; + double det=vecAB.Det(vecBC); + if(fabs(det)<J_EPS) det=0.0; - return ( det<=0.0 ); + return ( det<=0.0 ); } /************************************************************ NormalSubRoom ************************************************************/ -NormalSubRoom::NormalSubRoom() : SubRoom() { - -} - -NormalSubRoom::NormalSubRoom(const NormalSubRoom& orig) : SubRoom(orig) { - -} - -NormalSubRoom::~NormalSubRoom() { -} - -string NormalSubRoom::WriteSubRoom() const { - string s; - for (int j = 0; j < GetNumberOfWalls(); j++) { - - const Wall& w = GetWall(j); - string geometry; - char wall[CLENGTH] = ""; - geometry.append("\t\t<wall>\n"); - sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", - (w.GetPoint1().GetX()) * FAKTOR, - (w.GetPoint1().GetY()) * FAKTOR, - GetElevation(w.GetPoint1())*FAKTOR); - geometry.append(wall); - sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", - (w.GetPoint2().GetX()) * FAKTOR, - (w.GetPoint2().GetY()) * FAKTOR, - GetElevation(w.GetPoint2())*FAKTOR); - geometry.append(wall); - geometry.append("\t\t</wall>\n"); - - s.append(geometry); - //s.append(GetWall(j).Write()); - } - //add the subroom caption - Point pos = GetCentroid(); - char tmp[CLENGTH]; - sprintf(tmp, "\t\t<label centerX=\"%.2f\" centerY=\"%.2f\" centerZ=\"0\" text=\"%d\" color=\"100\" />\n" - , pos.GetX() * FAKTOR, pos.GetY() * FAKTOR, GetSubRoomID()); - s.append(tmp); - - //write the obstacles - for( unsigned int j=0;j<GetAllObstacles().size(); j++) { - s.append(GetAllObstacles()[j]->Write()); - } - - return s; -} - -string NormalSubRoom::WritePolyLine() const { - - string s; - char tmp[CLENGTH]; - - s.append("\t<Obstacle closed=\"1\" boundingbox=\"0\" class=\"1\">\n"); - for (unsigned int j = 0; j < _poly.size(); j++) { - sprintf(tmp, "\t\t<Vertex p_x = \"%.2lf\" p_y = \"%.2lf\"/>\n",_poly[j].GetX(),_poly[j].GetY()); - s.append(tmp); - } - s.append("\t</Obstacle>\n"); - - //write the obstacles - for( unsigned int j=0;j<GetAllObstacles().size(); j++) { - s.append(GetAllObstacles()[j]->Write()); - } - - return s; -} - -void NormalSubRoom::WriteToErrorLog() const { - Log->Write("\t\tNormal SubRoom:\n"); - for (int i = 0; i < GetNumberOfWalls(); i++) { - Wall w = GetWall(i); - w.WriteToErrorLog(); - } -} - -void NormalSubRoom::ConvertLineToPoly(vector<Line*> goals) { - vector<Line*> copy; - vector<Point> tmpPoly; - Point point; - Line* line; - // Alle Linienelemente in copy speichern - for (int i = 0; i < GetNumberOfWalls(); i++) { - copy.push_back(&_walls[i]); - } - // Transitions und Crossings sind in goal abgespeichert - copy.insert(copy.end(), goals.begin(), goals.end()); - - 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: \tNormalSubRoom::ConvertLineToPoly(): SubRoom %d Room %d Anfangspunkt ungleich Endpunkt!!!\n" - "\t(%f, %f) != (%f, %f)\n", GetSubRoomID(), GetRoomID(), tmpPoly[0].GetX(), tmpPoly[0].GetY(), point.GetX(), - point.GetY()); - Log->Write(tmp); - sprintf(tmp, "ERROR: \tDistance between the points: %lf !!!\n", (tmpPoly[0] - point).Norm()); - Log->Write(tmp); - exit(EXIT_FAILURE); - } - _poly = tmpPoly; +NormalSubRoom::NormalSubRoom() : SubRoom() +{ + +} + +NormalSubRoom::NormalSubRoom(const NormalSubRoom& orig) : SubRoom(orig) +{ + +} + +NormalSubRoom::~NormalSubRoom() +{ +} + +string NormalSubRoom::WriteSubRoom() const +{ + string s; + for (int j = 0; j < GetNumberOfWalls(); j++) { + + const Wall& w = GetWall(j); + string geometry; + char wall[CLENGTH] = ""; + geometry.append("\t\t<wall>\n"); + sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", + (w.GetPoint1().GetX()) * FAKTOR, + (w.GetPoint1().GetY()) * FAKTOR, + GetElevation(w.GetPoint1())*FAKTOR); + geometry.append(wall); + sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", + (w.GetPoint2().GetX()) * FAKTOR, + (w.GetPoint2().GetY()) * FAKTOR, + GetElevation(w.GetPoint2())*FAKTOR); + geometry.append(wall); + geometry.append("\t\t</wall>\n"); + + s.append(geometry); + //s.append(GetWall(j).Write()); + } + //add the subroom caption + Point pos = GetCentroid(); + char tmp[CLENGTH]; + sprintf(tmp, "\t\t<label centerX=\"%.2f\" centerY=\"%.2f\" centerZ=\"0\" text=\"%d\" color=\"100\" />\n" + , pos.GetX() * FAKTOR, pos.GetY() * FAKTOR, GetSubRoomID()); + s.append(tmp); + + //write the obstacles + for( unsigned int j=0; j<GetAllObstacles().size(); j++) { + s.append(GetAllObstacles()[j]->Write()); + } + + return s; +} + +string NormalSubRoom::WritePolyLine() const +{ + + string s; + char tmp[CLENGTH]; + + s.append("\t<Obstacle closed=\"1\" boundingbox=\"0\" class=\"1\">\n"); + for (unsigned int j = 0; j < _poly.size(); j++) { + sprintf(tmp, "\t\t<Vertex p_x = \"%.2lf\" p_y = \"%.2lf\"/>\n",_poly[j].GetX(),_poly[j].GetY()); + s.append(tmp); + } + s.append("\t</Obstacle>\n"); + + //write the obstacles + for( unsigned int j=0; j<GetAllObstacles().size(); j++) { + s.append(GetAllObstacles()[j]->Write()); + } + + return s; +} + +void NormalSubRoom::WriteToErrorLog() const +{ + Log->Write("\t\tNormal SubRoom:\n"); + for (int i = 0; i < GetNumberOfWalls(); i++) { + Wall w = GetWall(i); + w.WriteToErrorLog(); + } +} + +void NormalSubRoom::ConvertLineToPoly(vector<Line*> goals) +{ + vector<Line*> copy; + vector<Point> tmpPoly; + Point point; + Line* line; + // Alle Linienelemente in copy speichern + for (int i = 0; i < GetNumberOfWalls(); i++) { + copy.push_back(&_walls[i]); + } + // Transitions und Crossings sind in goal abgespeichert + copy.insert(copy.end(), goals.begin(), goals.end()); + + 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: \tNormalSubRoom::ConvertLineToPoly(): SubRoom %d Room %d Anfangspunkt ungleich Endpunkt!!!\n" + "\t(%f, %f) != (%f, %f)\n", GetSubRoomID(), GetRoomID(), tmpPoly[0].GetX(), tmpPoly[0].GetY(), point.GetX(), + point.GetY()); + Log->Write(tmp); + sprintf(tmp, "ERROR: \tDistance between the points: %lf !!!\n", (tmpPoly[0] - point).Norm()); + Log->Write(tmp); + exit(EXIT_FAILURE); + } + _poly = tmpPoly; } @@ -646,373 +689,399 @@ void NormalSubRoom::ConvertLineToPoly(vector<Line*> goals) { // gibt zuruck in welchen Quadranten vertex liegt, wobei hitPos der Koordinatenursprung ist -int NormalSubRoom::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); +int NormalSubRoom::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); } // x-Koordinate der Linie von einer Eccke zur nächsten -double NormalSubRoom::Xintercept(const Point& point1, const Point& point2, double hitY) const { - return (point2.GetX() - (((point2.GetY() - hitY) * (point1.GetX() - point2.GetX())) / - (point1.GetY() - point2.GetY()))); +double NormalSubRoom::Xintercept(const Point& point1, const Point& point2, double hitY) const +{ + return (point2.GetX() - (((point2.GetY() - hitY) * (point1.GetX() - point2.GetX())) / + (point1.GetY() - point2.GetY()))); } // neue Version auch für konkave Polygone -bool NormalSubRoom::IsInSubRoom(const Point& ped) const { - 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._y) > ped._x) - 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 NormalSubRoom::IsInSubRoom(const Point& ped) const +{ + 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._y) > ped._x) + 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; } /************************************************************ Stair ************************************************************/ -Stair::Stair() : NormalSubRoom() { - pUp = Point(); - pDown = Point(); +Stair::Stair() : NormalSubRoom() +{ + pUp = Point(); + pDown = Point(); } -Stair::Stair(const Stair & orig) : NormalSubRoom(orig) { - pUp = orig.GetUp(); - pDown = orig.GetDown(); +Stair::Stair(const Stair & orig) : NormalSubRoom(orig) +{ + pUp = orig.GetUp(); + pDown = orig.GetDown(); } -Stair::~Stair() { +Stair::~Stair() +{ } // Setter-Funktionen -void Stair::SetUp(const Point & p) { - pUp = p; +void Stair::SetUp(const Point & p) +{ + pUp = p; } -void Stair::SetDown(const Point & p) { - pDown = p; +void Stair::SetDown(const Point & p) +{ + pDown = p; } // Getter-Funktionen -const Point & Stair::GetUp() const { - return pUp; +const Point & Stair::GetUp() const +{ + return pUp; } -const Point & Stair::GetDown() const { - return pDown; +const Point & Stair::GetDown() const +{ + return pDown; } -string Stair::WriteSubRoom() const { - string s; - - for (int j = 0; j < GetNumberOfWalls(); j++) { - const Wall& w = GetWall(j); +string Stair::WriteSubRoom() const +{ + string s; + + for (int j = 0; j < GetNumberOfWalls(); j++) { + const Wall& w = GetWall(j); + + string geometry; + char wall[CLENGTH] = ""; + geometry.append("\t\t<wall>\n"); + sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", + (w.GetPoint1().GetX()) * FAKTOR, + (w.GetPoint1().GetY()) * FAKTOR, + GetElevation(w.GetPoint1())*FAKTOR); + geometry.append(wall); + sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", + (w.GetPoint2().GetX()) * FAKTOR, + (w.GetPoint2().GetY()) * FAKTOR, + GetElevation(w.GetPoint2())*FAKTOR); + geometry.append(wall); + geometry.append("\t\t</wall>\n"); + + s.append(geometry); + //s.append(w.Write()); + } + //Line tmp = Line(GetUp(), GetDown()); + // s.append(tmp.Write()); + Point pos = GetCentroid(); + char tmp_c[CLENGTH]; + sprintf(tmp_c, "\t\t<sphere centerX=\"%.2f\" centerY=\"%.2f\" centerZ=\"%.2f\" radius=\"20\" color=\"100\" />\n" + , GetUp().GetX() * FAKTOR, GetUp().GetY() * FAKTOR, GetElevation(GetUp())*FAKTOR); + s.append(tmp_c); + + //add the subroom caption + sprintf(tmp_c, "\t\t<label centerX=\"%.2f\" centerY=\"%.2f\" centerZ=\"%.2f\" text=\"%d\" color=\"100\" />\n" + , pos.GetX() * FAKTOR, pos.GetY() * FAKTOR,GetElevation(pos)*FAKTOR ,GetSubRoomID()); + s.append(tmp_c); + + return s; +} + +string Stair::WritePolyLine() const +{ - string geometry; - char wall[CLENGTH] = ""; - geometry.append("\t\t<wall>\n"); - sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", - (w.GetPoint1().GetX()) * FAKTOR, - (w.GetPoint1().GetY()) * FAKTOR, - GetElevation(w.GetPoint1())*FAKTOR); - geometry.append(wall); - sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", - (w.GetPoint2().GetX()) * FAKTOR, - (w.GetPoint2().GetY()) * FAKTOR, - GetElevation(w.GetPoint2())*FAKTOR); - geometry.append(wall); - geometry.append("\t\t</wall>\n"); + string s; + char tmp[CLENGTH]; - s.append(geometry); - //s.append(w.Write()); - } - //Line tmp = Line(GetUp(), GetDown()); - // s.append(tmp.Write()); - Point pos = GetCentroid(); - char tmp_c[CLENGTH]; - sprintf(tmp_c, "\t\t<sphere centerX=\"%.2f\" centerY=\"%.2f\" centerZ=\"%.2f\" radius=\"20\" color=\"100\" />\n" - , GetUp().GetX() * FAKTOR, GetUp().GetY() * FAKTOR, GetElevation(GetUp())*FAKTOR); - s.append(tmp_c); + s.append("\t<Obstacle closed=\"1\" boundingbox=\"0\" class=\"1\">\n"); + for (unsigned int j = 0; j < _poly.size(); j++) { + sprintf(tmp, "\t\t<Vertex p_x = \"%.2lf\" p_y = \"%.2lf\"/>\n",_poly[j].GetX(),_poly[j].GetY()); + s.append(tmp); + } + s.append("\t</Obstacle>\n"); - //add the subroom caption - sprintf(tmp_c, "\t\t<label centerX=\"%.2f\" centerY=\"%.2f\" centerZ=\"%.2f\" text=\"%d\" color=\"100\" />\n" - , pos.GetX() * FAKTOR, pos.GetY() * FAKTOR,GetElevation(pos)*FAKTOR ,GetSubRoomID()); - s.append(tmp_c); + //write the obstacles + for( unsigned int j=0; j<GetAllObstacles().size(); j++) { + s.append(GetAllObstacles()[j]->Write()); + } - return s; + return s; +} +void Stair::WriteToErrorLog() const +{ + Log->Write("\t\tStair:\n"); + for (int i = 0; i < GetNumberOfWalls(); i++) { + Wall w = GetWall(i); + w.WriteToErrorLog(); + } } -string Stair::WritePolyLine() const { +/* prüft ob die Punkte p1, p2 und p3 auf einer Linie liegen, oder eine Ecke bilden. + * Dabei liegt p2 IMMER in der Mitte und entspricht aktPoint + * */ +const Point* Stair::CheckCorner(const Point** otherPoint, const Point** aktPoint, const Point* nextPoint) +{ - string s; - char tmp[CLENGTH]; + Point l1 = **otherPoint - **aktPoint; + Point l2 = *nextPoint - **aktPoint; + const Point* rueck = NULL; + // Punkte bilden eine Linie + if (fabs(fabs(l1.ScalarP(l2) / (l1.Norm() * l2.Norm())) - 1) < 0.1) { + *aktPoint = nextPoint; + } else { // aktPoint/p2 ist eine Ecke + rueck = *aktPoint; + *otherPoint = *aktPoint; + *aktPoint = nextPoint; + } + return rueck; +} + +void Stair::ConvertLineToPoly(vector<Line*> goals) +{ - s.append("\t<Obstacle closed=\"1\" boundingbox=\"0\" class=\"1\">\n"); - for (unsigned int j = 0; j < _poly.size(); j++) { - sprintf(tmp, "\t\t<Vertex p_x = \"%.2lf\" p_y = \"%.2lf\"/>\n",_poly[j].GetX(),_poly[j].GetY()); - s.append(tmp); - } - s.append("\t</Obstacle>\n"); + //return NormalSubRoom::ConvertLineToPoly(goals); + + vector<Line*> copy; + vector<Point> orgPoly = vector<Point > (); + const Point* aktPoint; + const Point* otherPoint; + const Point* nextPoint; + const Point* firstAktPoint; + const Point* firstOtherPoint; + Line *nextLine; + + // Alle Linienelemente in copy speichern + for (int i = 0; i < GetNumberOfWalls(); i++) { + copy.push_back(&_walls[i]); + } + // Transitions und Crossings sind in goal abgespeichert + copy.insert(copy.end(), goals.begin(), goals.end()); + + aktPoint = ©[0]->GetPoint1(); + firstAktPoint = aktPoint; + otherPoint = ©[0]->GetPoint2(); + firstOtherPoint = otherPoint; + copy.erase(copy.begin()); + + // Polygon aus allen Linen erzeugen + for (int i = 0; i < (int) copy.size(); i++) { + nextLine = copy[i]; + nextPoint = NULL; + if ((*aktPoint - nextLine->GetPoint1()).Norm() < J_TOLERANZ) { + nextPoint = &nextLine->GetPoint2(); + } else if ((*aktPoint - nextLine->GetPoint2()).Norm() < J_TOLERANZ) { + nextPoint = &nextLine->GetPoint1(); + } + if (nextPoint != NULL) { + const Point* rueck = CheckCorner(&otherPoint, &aktPoint, nextPoint); + if (rueck != NULL) + orgPoly.push_back(*rueck); + copy.erase(copy.begin() + i); + i = -1; // von vorne suchen + } + } + if ((*aktPoint - *firstOtherPoint).Norm() < J_TOLERANZ) { + const Point* rueck = CheckCorner(&otherPoint, &aktPoint, firstAktPoint); + if (rueck != NULL) + orgPoly.push_back(*rueck); + } else { + char tmp[CLENGTH]; + double x1, y1, x2, y2; + x1 = firstOtherPoint->GetX(); + y1 = firstOtherPoint->GetY(); + x2 = aktPoint->GetX(); + y2 = aktPoint->GetY(); + sprintf(tmp, "ERROR: \tStair::ConvertLineToPoly(): SubRoom %d Room %d Anfangspunkt ungleich Endpunkt!!!\n" + "\t(%f, %f) != (%f, %f)\n", GetSubRoomID(), GetRoomID(), x1, y1, x2, y2); + Log->Write(tmp); + exit(EXIT_FAILURE); + } + + if (orgPoly.size() != 4) { + char tmp[CLENGTH]; + sprintf(tmp, "ERROR: \tStair::ConvertLineToPoly(): Stair %d Room %d ist kein Viereck!!!\n" + "Anzahl Ecken: %d\n", GetSubRoomID(), (int)GetRoomID(), (int)orgPoly.size()); + Log->Write(tmp); + exit(EXIT_FAILURE); + } + vector<Point> neuPoly = (orgPoly); + // ganz kleine Treppen (nur eine Stufe) nicht + if ((neuPoly[0] - neuPoly[1]).Norm() > 0.9 && (neuPoly[1] - neuPoly[2]).Norm() > 0.9) { + for (int i1 = 0; i1 < (int) orgPoly.size(); i1++) { + int i2 = (i1 + 1) % orgPoly.size(); + int i3 = (i2 + 1) % orgPoly.size(); + int i4 = (i3 + 1) % orgPoly.size(); + Point p1 = neuPoly[i1]; + Point p2 = neuPoly[i2]; + Point p3 = neuPoly[i3]; + Point p4 = neuPoly[i4]; + + Point l1 = p2 - p1; + Point l2 = p3 - p2; + + if (l1.Norm() < l2.Norm()) { + neuPoly[i2] = neuPoly[i2] + l1.Normalized() * 2 * J_EPS_GOAL; + l2 = p3 - p4; + neuPoly[i3] = neuPoly[i3] + l2.Normalized() * 2 * J_EPS_GOAL; + } + } + } + _poly = neuPoly; +} + +bool Stair::IsInSubRoom(const Point& ped) const +{ + bool rueck = false; + int N = (int) _poly.size(); + int sum = 0; - //write the obstacles - for( unsigned int j=0;j<GetAllObstacles().size(); j++) { - s.append(GetAllObstacles()[j]->Write()); - } + for (int i = 0; i < N; i++) { + Line l = Line(_poly[i], _poly[(i + 1) % N]); + Point s = l.LotPoint(ped); + if (l.IsInLineSegment(s)) + sum++; + } + if (sum == 4) + rueck = true; - return s; + return rueck; } -void Stair::WriteToErrorLog() const { - Log->Write("\t\tStair:\n"); - for (int i = 0; i < GetNumberOfWalls(); i++) { - Wall w = GetWall(i); - w.WriteToErrorLog(); - } + + +void SubRoom::SetType(const std::string& type) +{ + _type = type; } -/* prüft ob die Punkte p1, p2 und p3 auf einer Linie liegen, oder eine Ecke bilden. - * Dabei liegt p2 IMMER in der Mitte und entspricht aktPoint - * */ -const Point* Stair::CheckCorner(const Point** otherPoint, const Point** aktPoint, const Point* nextPoint) { - - Point l1 = **otherPoint - **aktPoint; - Point l2 = *nextPoint - **aktPoint; - const Point* rueck = NULL; - // Punkte bilden eine Linie - if (fabs(fabs(l1.ScalarP(l2) / (l1.Norm() * l2.Norm())) - 1) < 0.1) { - *aktPoint = nextPoint; - } else // aktPoint/p2 ist eine Ecke - { - rueck = *aktPoint; - *otherPoint = *aktPoint; - *aktPoint = nextPoint; - } - return rueck; -} - -void Stair::ConvertLineToPoly(vector<Line*> goals) { - - //return NormalSubRoom::ConvertLineToPoly(goals); - - vector<Line*> copy; - vector<Point> orgPoly = vector<Point > (); - const Point* aktPoint; - const Point* otherPoint; - const Point* nextPoint; - const Point* firstAktPoint; - const Point* firstOtherPoint; - Line *nextLine; - - // Alle Linienelemente in copy speichern - for (int i = 0; i < GetNumberOfWalls(); i++) { - copy.push_back(&_walls[i]); - } - // Transitions und Crossings sind in goal abgespeichert - copy.insert(copy.end(), goals.begin(), goals.end()); - - aktPoint = ©[0]->GetPoint1(); - firstAktPoint = aktPoint; - otherPoint = ©[0]->GetPoint2(); - firstOtherPoint = otherPoint; - copy.erase(copy.begin()); - - // Polygon aus allen Linen erzeugen - for (int i = 0; i < (int) copy.size(); i++) { - nextLine = copy[i]; - nextPoint = NULL; - if ((*aktPoint - nextLine->GetPoint1()).Norm() < J_TOLERANZ) { - nextPoint = &nextLine->GetPoint2(); - } else if ((*aktPoint - nextLine->GetPoint2()).Norm() < J_TOLERANZ) { - nextPoint = &nextLine->GetPoint1(); - } - if (nextPoint != NULL) { - const Point* rueck = CheckCorner(&otherPoint, &aktPoint, nextPoint); - if (rueck != NULL) - orgPoly.push_back(*rueck); - copy.erase(copy.begin() + i); - i = -1; // von vorne suchen - } - } - if ((*aktPoint - *firstOtherPoint).Norm() < J_TOLERANZ) { - const Point* rueck = CheckCorner(&otherPoint, &aktPoint, firstAktPoint); - if (rueck != NULL) - orgPoly.push_back(*rueck); - } else { - char tmp[CLENGTH]; - double x1, y1, x2, y2; - x1 = firstOtherPoint->GetX(); - y1 = firstOtherPoint->GetY(); - x2 = aktPoint->GetX(); - y2 = aktPoint->GetY(); - sprintf(tmp, "ERROR: \tStair::ConvertLineToPoly(): SubRoom %d Room %d Anfangspunkt ungleich Endpunkt!!!\n" - "\t(%f, %f) != (%f, %f)\n", GetSubRoomID(), GetRoomID(), x1, y1, x2, y2); - Log->Write(tmp); - exit(EXIT_FAILURE); - } - - if (orgPoly.size() != 4) { - char tmp[CLENGTH]; - sprintf(tmp, "ERROR: \tStair::ConvertLineToPoly(): Stair %d Room %d ist kein Viereck!!!\n" - "Anzahl Ecken: %d\n", GetSubRoomID(), (int)GetRoomID(), (int)orgPoly.size()); - Log->Write(tmp); - exit(EXIT_FAILURE); - } - vector<Point> neuPoly = (orgPoly); - // ganz kleine Treppen (nur eine Stufe) nicht - if ((neuPoly[0] - neuPoly[1]).Norm() > 0.9 && (neuPoly[1] - neuPoly[2]).Norm() > 0.9) { - for (int i1 = 0; i1 < (int) orgPoly.size(); i1++) { - int i2 = (i1 + 1) % orgPoly.size(); - int i3 = (i2 + 1) % orgPoly.size(); - int i4 = (i3 + 1) % orgPoly.size(); - Point p1 = neuPoly[i1]; - Point p2 = neuPoly[i2]; - Point p3 = neuPoly[i3]; - Point p4 = neuPoly[i4]; - - Point l1 = p2 - p1; - Point l2 = p3 - p2; - - if (l1.Norm() < l2.Norm()) { - neuPoly[i2] = neuPoly[i2] + l1.Normalized() * 2 * J_EPS_GOAL; - l2 = p3 - p4; - neuPoly[i3] = neuPoly[i3] + l2.Normalized() * 2 * J_EPS_GOAL; - } - } - } - _poly = neuPoly; -} - -bool Stair::IsInSubRoom(const Point& ped) const { - bool rueck = false; - int N = (int) _poly.size(); - int sum = 0; - - for (int i = 0; i < N; i++) { - Line l = Line(_poly[i], _poly[(i + 1) % N]); - Point s = l.LotPoint(ped); - if (l.IsInLineSegment(s)) - sum++; - } - if (sum == 4) - rueck = true; - - return rueck; -} - - -void SubRoom::SetType(const std::string& type) { - _type = type; -} - -const std::string& SubRoom::GetType() const { - return _type; +const std::string& SubRoom::GetType() const +{ + return _type; } #ifdef _SIMULATOR -void SubRoom::SetAllPedestrians(const vector<Pedestrian*>& peds) { - _peds = peds; +void SubRoom::SetAllPedestrians(const vector<Pedestrian*>& peds) +{ + _peds = peds; } -void SubRoom::SetPedestrian(Pedestrian* ped, int index) { - if ((index >= 0) && (index < GetNumberOfPedestrians())) { - _peds[index] = ped; - } else { - Log->Write("ERROR: Wrong Index in SubRoom::SetPedestrian()"); - exit(0); - } +void SubRoom::SetPedestrian(Pedestrian* ped, int index) +{ + if ((index >= 0) && (index < GetNumberOfPedestrians())) { + _peds[index] = ped; + } else { + Log->Write("ERROR: Wrong Index in SubRoom::SetPedestrian()"); + exit(0); + } } -bool SubRoom::IsInSubRoom(Pedestrian* ped) const { - //TODO: reference ? - Point pos = ped->GetPos(); - if (ped->GetExitLine()->DistTo(pos) <= J_EPS_GOAL) - return true; - else - return IsInSubRoom(pos); +bool SubRoom::IsInSubRoom(Pedestrian* ped) const +{ + //TODO: reference ? + Point pos = ped->GetPos(); + if (ped->GetExitLine()->DistTo(pos) <= J_EPS_GOAL) + return true; + else + return IsInSubRoom(pos); } -int SubRoom::GetNumberOfPedestrians() const { - return _peds.size(); +int SubRoom::GetNumberOfPedestrians() const +{ + return _peds.size(); } -const vector<Pedestrian*>& SubRoom::GetAllPedestrians() const { - return _peds; +const vector<Pedestrian*>& SubRoom::GetAllPedestrians() const +{ + return _peds; } -Pedestrian* SubRoom::GetPedestrian(int index) const { - if ((index >= 0) && (index < (int) GetNumberOfPedestrians())) - return _peds[index]; - else { - Log->Write("ERROR: Wrong 'index' in SubRoom::GetPedestrian()"); - exit(0); - } +Pedestrian* SubRoom::GetPedestrian(int index) const +{ + if ((index >= 0) && (index < (int) GetNumberOfPedestrians())) + return _peds[index]; + else { + Log->Write("ERROR: Wrong 'index' in SubRoom::GetPedestrian()"); + exit(0); + } } -void SubRoom::AddPedestrian(Pedestrian* ped) { - _peds.push_back(ped); +void SubRoom::AddPedestrian(Pedestrian* ped) +{ + _peds.push_back(ped); } -void SubRoom::DeletePedestrian(int index) { - if ((index >= 0) && (index < (int) GetNumberOfPedestrians())) { - _peds.erase(_peds.begin() + index); +void SubRoom::DeletePedestrian(int index) +{ + if ((index >= 0) && (index < (int) GetNumberOfPedestrians())) { + _peds.erase(_peds.begin() + index); - } else { - Log->Write("ERROR: Wrong Index in SubRoom::DeletePedestrian()"); - exit(0); - } + } else { + Log->Write("ERROR: Wrong Index in SubRoom::DeletePedestrian()"); + exit(0); + } } -void SubRoom::ClearAllPedestrians(){ - for(unsigned int p=0;p<_peds.size();p++){ - delete _peds[p]; - } - _peds.clear(); +void SubRoom::ClearAllPedestrians() +{ + for(unsigned int p=0; p<_peds.size(); p++) { + delete _peds[p]; + } + _peds.clear(); } #endif // _SIMULATOR diff --git a/geometry/SubRoom.h b/geometry/SubRoom.h index 6cacfcf6035528ca736b87c2a9101ab2ff931b9e..3d9dcc8d7b7d463693e308415d3fc06562081e3f 100644 --- a/geometry/SubRoom.h +++ b/geometry/SubRoom.h @@ -50,284 +50,284 @@ class Pedestrian; ************************************************************/ class SubRoom { - private: - /// the id set using the SetID method - int _id; - /// the unique id resulting from the count of all subrooms in the system - int _uid; - int _roomID; - std::vector<int> _goalIDs; // all navigation lines contained in this subroom - double _area; - double _closed; - //defined by: Z = Ax + By + C - double _planeEquation[3]; - double _cosAngleWithHorizontalPlane; - std::string _type; - - std::vector<Obstacle*> _obstacles; // obstacles - - //different types of navigation lines - std::vector<Crossing*> _crossings; - std::vector<Transition*> _transitions; - std::vector<Hline*> _hlines; - - /// storing and incrementing the total number of subrooms - static int _static_uid; +private: + /// the id set using the SetID method + int _id; + /// the unique id resulting from the count of all subrooms in the system + int _uid; + int _roomID; + std::vector<int> _goalIDs; // all navigation lines contained in this subroom + double _area; + double _closed; + //defined by: Z = Ax + By + C + double _planeEquation[3]; + double _cosAngleWithHorizontalPlane; + std::string _type; + + std::vector<Obstacle*> _obstacles; // obstacles + + //different types of navigation lines + std::vector<Crossing*> _crossings; + std::vector<Transition*> _transitions; + std::vector<Hline*> _hlines; + + /// storing and incrementing the total number of subrooms + static int _static_uid; #ifdef _SIMULATOR - std::vector<Pedestrian*> _peds; // pedestrians container + std::vector<Pedestrian*> _peds; // pedestrians container #endif - protected: - std::vector<Wall> _walls; - std::vector<Point> _poly; // Polygonal representation of the subroom - - public: - - // constructors - SubRoom(); - SubRoom(const SubRoom& orig); - virtual ~SubRoom(); - - /** - * Set/Get the subroom id - */ - void SetSubRoomID(int ID); - - /** - * Set/Get the associated room id - */ - void SetRoomID(int ID); - //void SetAllWalls(const std::vector<Wall>& walls); - //void SetWall(const Wall& wall, int index); - //void SetPolygon(const std::vector<Point>& poly); - //void SetArea(double a); - - void SetClosed(double c); - - /** - * Set the plane equation for this subroom. - * defined by: Z = Ax + By + C - */ - void SetPlanEquation(double A, double B, double C); - - /** - * Set/Get the subroom id - */ - int GetSubRoomID() const; - - /** - * @return the number of walls forming this subroom - */ - int GetNumberOfWalls() const; - - /** - * @return all walls - */ - const std::vector<Wall>& GetAllWalls() const; - - /** - * @return a reference to the wall at position index - */ - const Wall& GetWall(int index) const; - - /** - * @return the polygonal representation of the subroom - * counterclockwise - */ - const std::vector<Point>& GetPolygon() const; - - /** - * @return a reference to all obstacles contained - */ - const std::vector<Obstacle*>& GetAllObstacles() const; - - /** - * @return the number of hlines+transitions+crossings - */ - int GetNumberOfGoalIDs() const; - - /** - * @return a vector containing all Ids - */ - const std::vector<int>& GetAllGoalIDs() const; - - /** - * @return the room containing this subroom - */ - int GetRoomID() const; - - /** - * @return the unique identifier for this subroom - */ - int GetUID() const; - - /** - * Set/Get the type of the subroom. - * Possible types are: stairs, room and floor. - * @return the type of the subroom. - */ - const std::string& GetType() const; - - /** - * Set/Get the type of the subroom. - * Possible types are: stairs, room and floor. - * @return the type of the subroom. - */ - void SetType(const std::string& type); - - - /** - * @return the status - */ - double GetClosed() const; - - /** - * @return the area - */ - double GetArea() const; - - /** - * @return the centroid of the subroom - * @see http://en.wikipedia.org/wiki/Centroid - */ - Point GetCentroid() const; - - /** - * @return the three coefficients of the plane equation. - * defined by: Z = Ax + By + C - */ - const double * GetPlanEquation () const; - - /** - * @return the elevation of a 2Dimensional point using the plane equation. - * @see GetPlanEquation - */ - double GetElevation(const Point & p1) const; - - - /** - * compute the cosine of the dihedral angle with the Horizontal plane Z=h - * @return the cosine of the angle - */ - double GetCosAngleWithHorizontal() const; - - /** - * Compute the area of the subroom. - * @see GetArea() - */ - void CalculateArea(); - - /** - * @return true if the polygon is convex - * @see http://stackoverflow.com/questions/471962/how-do-determine-if-a-polygon-is-complex-convex-nonconvex - */ - bool IsConvex(); - - /** - * @return true if the polygon is clockwise oriented - * @see http://stackoverflow.com/questions/9473570/polygon-vertices-clockwise-or-counterclockwise/ - */ - bool IsClockwise(); - - - /** - * check the subroom for some inconsistencies. - * e.g. simple polygons - * no intersection between the walls and the obstacles. - */ - void CheckObstacles(); - - /** - * Check the subroom for possible errors and - * output user specific informations. - */ - void SanityCheck(); - - //navigation - void AddCrossing(Crossing* line); - void AddTransition(Transition* line); - void AddHline(Hline* line); - - const std::vector<Crossing*>& GetAllCrossings() const; - const std::vector<Transition*>& GetAllTransitions() const; - const std::vector<Hline*>& GetAllHlines() const; - const Crossing* GetCrossing(int i) const; - const Transition* GetTransition(int i) const; - const Hline* GetHline(int i) const; - - - /** - * Add a wall to the subroom - */ - void AddWall(const Wall& w); - - /** - * Adds an obstacle to the subroom. - * They are used for the triangulation/convexifivation process - */ - void AddObstacle(Obstacle* obs); - - /** - * Remove the pedestrian from the subroom. - * @param index, the index of the peds in the vector (NOT THE ID !) - */ - void DeletePedestrian(int index); - //void DeletePedestrian(Pedestrian* ped); - void AddGoalID(int ID); - void RemoveGoalID(int ID); - - - - /** - * @return true if the two subrooms share a common walkable Edge (crossing or transition) - */ - bool IsDirectlyConnectedWith(const SubRoom* sub) const; - - /** - * @return true if the two segments are visible from each other. - * Alls walls and transitions and crossings are used in this check. - * The use of hlines is optional, because they are not real, can can be considered transparent - */ - bool IsVisible(Line* l1, Line* l2, bool considerHlines=false); - - /** - * @return true if the two points are visible from each other. - * Alls walls and transitions and crossings are used in this check. - * The use of hlines is optional, because they are not real, can be considered transparent - */ - bool IsVisible(const Point& p1, const Point& p2, bool considerHlines=false); - - - - // virtual functions - virtual std::string WriteSubRoom() const = 0; - virtual void WriteToErrorLog() const = 0; - virtual std::string WritePolyLine() const=0; +protected: + std::vector<Wall> _walls; + std::vector<Point> _poly; // Polygonal representation of the subroom + +public: + + // constructors + SubRoom(); + SubRoom(const SubRoom& orig); + virtual ~SubRoom(); + + /** + * Set/Get the subroom id + */ + void SetSubRoomID(int ID); + + /** + * Set/Get the associated room id + */ + void SetRoomID(int ID); + //void SetAllWalls(const std::vector<Wall>& walls); + //void SetWall(const Wall& wall, int index); + //void SetPolygon(const std::vector<Point>& poly); + //void SetArea(double a); + + void SetClosed(double c); + + /** + * Set the plane equation for this subroom. + * defined by: Z = Ax + By + C + */ + void SetPlanEquation(double A, double B, double C); + + /** + * Set/Get the subroom id + */ + int GetSubRoomID() const; + + /** + * @return the number of walls forming this subroom + */ + int GetNumberOfWalls() const; + + /** + * @return all walls + */ + const std::vector<Wall>& GetAllWalls() const; + + /** + * @return a reference to the wall at position index + */ + const Wall& GetWall(int index) const; + + /** + * @return the polygonal representation of the subroom + * counterclockwise + */ + const std::vector<Point>& GetPolygon() const; + + /** + * @return a reference to all obstacles contained + */ + const std::vector<Obstacle*>& GetAllObstacles() const; + + /** + * @return the number of hlines+transitions+crossings + */ + int GetNumberOfGoalIDs() const; + + /** + * @return a vector containing all Ids + */ + const std::vector<int>& GetAllGoalIDs() const; + + /** + * @return the room containing this subroom + */ + int GetRoomID() const; + + /** + * @return the unique identifier for this subroom + */ + int GetUID() const; + + /** + * Set/Get the type of the subroom. + * Possible types are: stairs, room and floor. + * @return the type of the subroom. + */ + const std::string& GetType() const; + + /** + * Set/Get the type of the subroom. + * Possible types are: stairs, room and floor. + * @return the type of the subroom. + */ + void SetType(const std::string& type); + + + /** + * @return the status + */ + double GetClosed() const; + + /** + * @return the area + */ + double GetArea() const; + + /** + * @return the centroid of the subroom + * @see http://en.wikipedia.org/wiki/Centroid + */ + Point GetCentroid() const; + + /** + * @return the three coefficients of the plane equation. + * defined by: Z = Ax + By + C + */ + const double * GetPlanEquation () const; + + /** + * @return the elevation of a 2Dimensional point using the plane equation. + * @see GetPlanEquation + */ + double GetElevation(const Point & p1) const; + + + /** + * compute the cosine of the dihedral angle with the Horizontal plane Z=h + * @return the cosine of the angle + */ + double GetCosAngleWithHorizontal() const; + + /** + * Compute the area of the subroom. + * @see GetArea() + */ + void CalculateArea(); + + /** + * @return true if the polygon is convex + * @see http://stackoverflow.com/questions/471962/how-do-determine-if-a-polygon-is-complex-convex-nonconvex + */ + bool IsConvex(); + + /** + * @return true if the polygon is clockwise oriented + * @see http://stackoverflow.com/questions/9473570/polygon-vertices-clockwise-or-counterclockwise/ + */ + bool IsClockwise(); + + + /** + * check the subroom for some inconsistencies. + * e.g. simple polygons + * no intersection between the walls and the obstacles. + */ + void CheckObstacles(); + + /** + * Check the subroom for possible errors and + * output user specific informations. + */ + void SanityCheck(); + + //navigation + void AddCrossing(Crossing* line); + void AddTransition(Transition* line); + void AddHline(Hline* line); + + const std::vector<Crossing*>& GetAllCrossings() const; + const std::vector<Transition*>& GetAllTransitions() const; + const std::vector<Hline*>& GetAllHlines() const; + const Crossing* GetCrossing(int i) const; + const Transition* GetTransition(int i) const; + const Hline* GetHline(int i) const; + + + /** + * Add a wall to the subroom + */ + void AddWall(const Wall& w); + + /** + * Adds an obstacle to the subroom. + * They are used for the triangulation/convexifivation process + */ + void AddObstacle(Obstacle* obs); + + /** + * Remove the pedestrian from the subroom. + * @param index, the index of the peds in the vector (NOT THE ID !) + */ + void DeletePedestrian(int index); + //void DeletePedestrian(Pedestrian* ped); + void AddGoalID(int ID); + void RemoveGoalID(int ID); + + + + /** + * @return true if the two subrooms share a common walkable Edge (crossing or transition) + */ + bool IsDirectlyConnectedWith(const SubRoom* sub) const; + + /** + * @return true if the two segments are visible from each other. + * Alls walls and transitions and crossings are used in this check. + * The use of hlines is optional, because they are not real, can can be considered transparent + */ + bool IsVisible(Line* l1, Line* l2, bool considerHlines=false); + + /** + * @return true if the two points are visible from each other. + * Alls walls and transitions and crossings are used in this check. + * The use of hlines is optional, because they are not real, can be considered transparent + */ + bool IsVisible(const Point& p1, const Point& p2, bool considerHlines=false); + + + + // virtual functions + virtual std::string WriteSubRoom() const = 0; + virtual void WriteToErrorLog() const = 0; + virtual std::string WritePolyLine() const=0; - /// convert all walls and transitions(doors) into a polygon representing the subroom - virtual void ConvertLineToPoly(std::vector<Line*> goals) = 0; - - ///check whether the pedestrians is still in the subroom - virtual bool IsInSubRoom(const Point& ped) const = 0; - - - // MPI: - void ClearAllPedestrians(); + /// convert all walls and transitions(doors) into a polygon representing the subroom + virtual void ConvertLineToPoly(std::vector<Line*> goals) = 0; + + ///check whether the pedestrians is still in the subroom + virtual bool IsInSubRoom(const Point& ped) const = 0; + + + // MPI: + void ClearAllPedestrians(); #ifdef _SIMULATOR - /** - * @return the number of pedestrians in this subroom - */ - int GetNumberOfPedestrians() const; - void AddPedestrian(Pedestrian* ped); - virtual bool IsInSubRoom(Pedestrian* ped) const; - void SetAllPedestrians(const std::vector<Pedestrian*>& peds); - void SetPedestrian(Pedestrian* ped, int index); - const std::vector<Pedestrian*>& GetAllPedestrians() const; - Pedestrian* GetPedestrian(int index) const; + /** + * @return the number of pedestrians in this subroom + */ + int GetNumberOfPedestrians() const; + void AddPedestrian(Pedestrian* ped); + virtual bool IsInSubRoom(Pedestrian* ped) const; + void SetAllPedestrians(const std::vector<Pedestrian*>& peds); + void SetPedestrian(Pedestrian* ped, int index); + const std::vector<Pedestrian*>& GetAllPedestrians() const; + Pedestrian* GetPedestrian(int index) const; #endif @@ -338,23 +338,23 @@ class SubRoom { ************************************************************/ class NormalSubRoom : public SubRoom { - private: +private: - ///@see IsInSubRoom - int WhichQuad(const Point& vertex, const Point& hitPos) const; - double Xintercept(const Point& point1, const Point& point2, double hitY) const; + ///@see IsInSubRoom + int WhichQuad(const Point& vertex, const Point& hitPos) const; + double Xintercept(const Point& point1, const Point& point2, double hitY) const; - public: - NormalSubRoom(); - NormalSubRoom(const NormalSubRoom& orig); - virtual ~NormalSubRoom(); +public: + NormalSubRoom(); + NormalSubRoom(const NormalSubRoom& orig); + virtual ~NormalSubRoom(); - std::string WriteSubRoom() const; - std::string WritePolyLine() const; + std::string WriteSubRoom() const; + std::string WritePolyLine() const; - void WriteToErrorLog() const; - void ConvertLineToPoly(std::vector<Line*> goals); - bool IsInSubRoom(const Point& ped) const; + void WriteToErrorLog() const; + void ConvertLineToPoly(std::vector<Line*> goals); + bool IsInSubRoom(const Point& ped) const; }; /************************************************************ @@ -362,34 +362,34 @@ class NormalSubRoom : public SubRoom { ************************************************************/ class Stair : public NormalSubRoom { - private: - Point pUp; /// Punkt der den oberen Bereich der Treppe markiert - Point pDown; /// Punkt der den unteren Bereich der Treppe markiert - - const Point* CheckCorner(const Point** otherPoint, const Point** aktPoint, const Point* nextPoint); - public: - Stair(); - Stair(const Stair& orig); - virtual ~Stair(); - - // Setter-Funktionen - void SetUp(const Point& p); - void SetDown(const Point& p); - - // Getter-Funktionen - const Point& GetUp() const; - const Point& GetDown() const; - - /// pedestrians are going the stairs downwards - bool IsUpStairs() const; - /// pedestrians are going the stairs upwards - bool IsDownStair() const; - - std::string WriteSubRoom() const; - std::string WritePolyLine() const; - virtual void WriteToErrorLog() const; - virtual void ConvertLineToPoly(std::vector<Line*> goals); - bool IsInSubRoom(const Point& ped) const; +private: + Point pUp; /// Punkt der den oberen Bereich der Treppe markiert + Point pDown; /// Punkt der den unteren Bereich der Treppe markiert + + const Point* CheckCorner(const Point** otherPoint, const Point** aktPoint, const Point* nextPoint); +public: + Stair(); + Stair(const Stair& orig); + virtual ~Stair(); + + // Setter-Funktionen + void SetUp(const Point& p); + void SetDown(const Point& p); + + // Getter-Funktionen + const Point& GetUp() const; + const Point& GetDown() const; + + /// pedestrians are going the stairs downwards + bool IsUpStairs() const; + /// pedestrians are going the stairs upwards + bool IsDownStair() const; + + std::string WriteSubRoom() const; + std::string WritePolyLine() const; + virtual void WriteToErrorLog() const; + virtual void ConvertLineToPoly(std::vector<Line*> goals); + bool IsInSubRoom(const Point& ped) const; }; #endif /* _SUBROOM_H */ diff --git a/geometry/Transition.cpp b/geometry/Transition.cpp index a22265d8b5a00917c920c35c699a7c365badda7e..731db710684e1b4a283ac7979b0c49c58c504aab 100644 --- a/geometry/Transition.cpp +++ b/geometry/Transition.cpp @@ -35,161 +35,180 @@ using namespace std; Transition (abgeleitet von Crossing) ************************************************************/ -Transition::Transition() : Crossing() { - _isOpen = true; - _doorUsage=0; - _lastPassingTime=0; - _room2 = NULL; +Transition::Transition() : Crossing() +{ + _isOpen = true; + _doorUsage=0; + _lastPassingTime=0; + _room2 = NULL; } -Transition::~Transition() { +Transition::~Transition() +{ } // Setter-Funktionen -void Transition::Close() { - _isOpen = false; +void Transition::Close() +{ + _isOpen = false; } -void Transition::Open() { - _isOpen = true; +void Transition::Open() +{ + _isOpen = true; } -void Transition::SetType(string type){ - _type=type; +void Transition::SetType(string type) +{ + _type=type; } -void Transition::SetRoom2(Room* r) { - _room2 = r; +void Transition::SetRoom2(Room* r) +{ + _room2 = r; } // Getter-Funktionen -bool Transition::IsOpen() const { - return _isOpen; +bool Transition::IsOpen() const +{ + return _isOpen; } -Room* Transition::GetRoom2() const { - return _room2; +Room* Transition::GetRoom2() const +{ + return _room2; } -string Transition::GetType() const { - return _type; +string Transition::GetType() const +{ + return _type; } // Sonstiges // gibt den ANDEREN room != roomID zurück -Room* Transition::GetOtherRoom(int roomID) const { - if (GetRoom1()!=NULL && GetRoom1()->GetID() == roomID) { - return GetRoom2(); - } else if (GetRoom2()!=NULL && GetRoom2()->GetID() == roomID) { - return GetRoom1(); - } else { - char msg[CLENGTH]; - sprintf(msg,"ERROR: \tTransition::GetOtherRoom() wrong roomID [%d]",roomID); - Log->Write(msg); - exit(0); - } +Room* Transition::GetOtherRoom(int roomID) const +{ + if (GetRoom1()!=NULL && GetRoom1()->GetID() == roomID) { + return GetRoom2(); + } else if (GetRoom2()!=NULL && GetRoom2()->GetID() == roomID) { + return GetRoom1(); + } else { + char msg[CLENGTH]; + sprintf(msg,"ERROR: \tTransition::GetOtherRoom() wrong roomID [%d]",roomID); + Log->Write(msg); + exit(0); + } } // virtuelle Funktionen // prüft ob Ausgang nach draußen -bool Transition::IsExit() const { - if(GetRoom1()!=NULL && _room2!=NULL) - return false; - else - return true; +bool Transition::IsExit() const +{ + if(GetRoom1()!=NULL && _room2!=NULL) + return false; + else + return true; } // prüft, ob Transition in Raum mit roomID -bool Transition::IsInRoom(int roomID) const { - bool c1 = false; - bool c2 = false; - if (GetRoom1() != NULL && GetRoom1()->GetID() == roomID) - c1 = true; - if (GetRoom2() != NULL && GetRoom2()->GetID() == roomID) - c2 = true; - return c1 || c2; +bool Transition::IsInRoom(int roomID) const +{ + bool c1 = false; + bool c2 = false; + if (GetRoom1() != NULL && GetRoom1()->GetID() == roomID) + c1 = true; + if (GetRoom2() != NULL && GetRoom2()->GetID() == roomID) + c2 = true; + return c1 || c2; } -bool Transition::IsTransition() const { - return true; +bool Transition::IsTransition() const +{ + return true; } /* gibt den ANDEREN Subroom mit GetRoomID() != roomID zurück * subroomID wird hier nicht benötigt, aber in Crossings::GetOtherSubRoom() * (virtuelle Funktion) */ -SubRoom* Transition::GetOtherSubRoom(int roomID, int subroomID) const { - if ((GetRoom1() != NULL) && (GetRoom1()->GetID() == roomID)) - return GetSubRoom2(); - else if ((GetRoom2() != NULL) && (GetRoom2()->GetID() == roomID)) - return GetSubRoom1(); - else { - Log->Write("ERROR: \tTransition::GetOtherSubRoom No exit found " - "on the other side\n ID=%d, roomID=%d, subroomID=%d\n",GetUniqueID(),roomID,subroomID); - exit(EXIT_FAILURE); - } +SubRoom* Transition::GetOtherSubRoom(int roomID, int subroomID) const +{ + if ((GetRoom1() != NULL) && (GetRoom1()->GetID() == roomID)) + return GetSubRoom2(); + else if ((GetRoom2() != NULL) && (GetRoom2()->GetID() == roomID)) + return GetSubRoom1(); + else { + Log->Write("ERROR: \tTransition::GetOtherSubRoom No exit found " + "on the other side\n ID=%d, roomID=%d, subroomID=%d\n",GetUniqueID(),roomID,subroomID); + exit(EXIT_FAILURE); + } } // Ein-Ausgbae -void Transition::WriteToErrorLog() const { - string s; - char tmp[CLENGTH]; - sprintf(tmp, "\t\tTRANS: %d [%s] (%f, %f) -- (%f, %f)\n", GetID(), GetCaption().c_str(), - GetPoint1().GetX(), GetPoint1().GetY(), GetPoint2().GetX(), GetPoint2().GetY()); - s.append(tmp); - // erster Raum - if (GetRoom1() != NULL) { - sprintf(tmp, "\t\t\t\tRoom: %d [%s] SubRoom: %d", GetRoom1()->GetID(), - GetRoom1()->GetCaption().c_str(), GetSubRoom1()->GetSubRoomID()); - } else { - sprintf(tmp, "\t\t\t\tAusgang"); - } - s.append(tmp); - // zweiter Raum - if (GetRoom2() != NULL) { - sprintf(tmp, " <->\tRoom: %d [%s] SubRoom: %d\n", GetRoom2()->GetID(), - GetRoom2()->GetCaption().c_str(), GetSubRoom2()->GetSubRoomID()); - } else { - sprintf(tmp, " <->\tAusgang\n"); - } - s.append(tmp); - Log->Write(s); +void Transition::WriteToErrorLog() const +{ + string s; + char tmp[CLENGTH]; + sprintf(tmp, "\t\tTRANS: %d [%s] (%f, %f) -- (%f, %f)\n", GetID(), GetCaption().c_str(), + GetPoint1().GetX(), GetPoint1().GetY(), GetPoint2().GetX(), GetPoint2().GetY()); + s.append(tmp); + // erster Raum + if (GetRoom1() != NULL) { + sprintf(tmp, "\t\t\t\tRoom: %d [%s] SubRoom: %d", GetRoom1()->GetID(), + GetRoom1()->GetCaption().c_str(), GetSubRoom1()->GetSubRoomID()); + } else { + sprintf(tmp, "\t\t\t\tAusgang"); + } + s.append(tmp); + // zweiter Raum + if (GetRoom2() != NULL) { + sprintf(tmp, " <->\tRoom: %d [%s] SubRoom: %d\n", GetRoom2()->GetID(), + GetRoom2()->GetCaption().c_str(), GetSubRoom2()->GetSubRoomID()); + } else { + sprintf(tmp, " <->\tAusgang\n"); + } + s.append(tmp); + Log->Write(s); } // TraVisTo Ausgabe -string Transition::WriteElement() const { - string geometry; - char tmp[CLENGTH] = ""; - - sprintf(tmp,"\t\t<door ID=\"%d\" color=\"180\" caption=\"%d_%d_%s\">\n",GetUniqueID(),GetID(),GetUniqueID(),GetCaption().c_str()); - geometry.append(tmp); - sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", - (GetPoint1().GetX()) * FAKTOR, - (GetPoint1().GetY()) * FAKTOR, - GetSubRoom1()->GetElevation(GetPoint1())*FAKTOR); - geometry.append(tmp); - sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", - (GetPoint2().GetX()) * FAKTOR, - (GetPoint2().GetY()) * FAKTOR, - GetSubRoom1()->GetElevation(GetPoint2())*FAKTOR); - geometry.append(tmp); - geometry.append("\t\t</door>\n"); - return geometry; -} - -void Transition::IncreaseDoorUsage(int number, double time) { - _doorUsage+=number; - _lastPassingTime=time; -} - -int Transition::GetDoorUsage() const { - return _doorUsage; -} - -double Transition::GetLastPassingTime() const { - return _lastPassingTime; +string Transition::WriteElement() const +{ + string geometry; + char tmp[CLENGTH] = ""; + + sprintf(tmp,"\t\t<door ID=\"%d\" color=\"180\" caption=\"%d_%d_%s\">\n",GetUniqueID(),GetID(),GetUniqueID(),GetCaption().c_str()); + geometry.append(tmp); + sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", + (GetPoint1().GetX()) * FAKTOR, + (GetPoint1().GetY()) * FAKTOR, + GetSubRoom1()->GetElevation(GetPoint1())*FAKTOR); + geometry.append(tmp); + sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", + (GetPoint2().GetX()) * FAKTOR, + (GetPoint2().GetY()) * FAKTOR, + GetSubRoom1()->GetElevation(GetPoint2())*FAKTOR); + geometry.append(tmp); + geometry.append("\t\t</door>\n"); + return geometry; +} + +void Transition::IncreaseDoorUsage(int number, double time) +{ + _doorUsage+=number; + _lastPassingTime=time; +} + +int Transition::GetDoorUsage() const +{ + return _doorUsage; +} + +double Transition::GetLastPassingTime() const +{ + return _lastPassingTime; } diff --git a/geometry/Transition.h b/geometry/Transition.h index 825c97da33f9a5677b7287d82b83d8dfe48ea00f..f447ae4aaec42971c18f253dfa8db666d6731269 100644 --- a/geometry/Transition.h +++ b/geometry/Transition.h @@ -34,86 +34,86 @@ class Room; class Subroom; class Transition : public Crossing { - private: - Room* _room2; - bool _isOpen; - std::string _type; - // number of agents that passed that exit - int _doorUsage; - double _lastPassingTime; - - public: - - Transition(); - virtual ~Transition(); - - /** - * Close the transition/door - */ - void Close(); - - /** - * Open the transition/door - */ - void Open(); - - /** - * Set/Get the type of the transition - * TODO: where is type defined? - */ - void SetType(std::string s); - - /** - * Set/Get the second room associated with this transition. - * The first one is set in the crossing class. - */ - void SetRoom2(Room* ID); - - /** - * Increment the number of persons that used that exit - * @param number, how many person have passed the door - * @param time, at which time - */ - void IncreaseDoorUsage(int number, double time); - - /** - * @return the number of pedestrians that used that exit. - */ - int GetDoorUsage() const; - - /** - * @return the last time this door was crossed - */ - double GetLastPassingTime() const; - - /** - * Set/Get the type of the transition - * TODO: where is type defined? - */ - std::string GetType() const; - - /** - * Set/Get the second room associated with this transition. - * The first one is set in the crossing class. - */ - Room* GetRoom2() const; - - - /** - * @return the other room. - */ - Room* GetOtherRoom(int room_id) const; - - // virtual functions - virtual bool IsOpen() const; - virtual bool IsExit() const; - virtual bool IsTransition() const; - virtual bool IsInRoom(int roomID) const; - virtual SubRoom* GetOtherSubRoom(int roomID, int subroomID) const; - - - virtual void WriteToErrorLog() const; - virtual std::string WriteElement() const; // TraVisTo Ausgabe +private: + Room* _room2; + bool _isOpen; + std::string _type; + // number of agents that passed that exit + int _doorUsage; + double _lastPassingTime; + +public: + + Transition(); + virtual ~Transition(); + + /** + * Close the transition/door + */ + void Close(); + + /** + * Open the transition/door + */ + void Open(); + + /** + * Set/Get the type of the transition + * TODO: where is type defined? + */ + void SetType(std::string s); + + /** + * Set/Get the second room associated with this transition. + * The first one is set in the crossing class. + */ + void SetRoom2(Room* ID); + + /** + * Increment the number of persons that used that exit + * @param number, how many person have passed the door + * @param time, at which time + */ + void IncreaseDoorUsage(int number, double time); + + /** + * @return the number of pedestrians that used that exit. + */ + int GetDoorUsage() const; + + /** + * @return the last time this door was crossed + */ + double GetLastPassingTime() const; + + /** + * Set/Get the type of the transition + * TODO: where is type defined? + */ + std::string GetType() const; + + /** + * Set/Get the second room associated with this transition. + * The first one is set in the crossing class. + */ + Room* GetRoom2() const; + + + /** + * @return the other room. + */ + Room* GetOtherRoom(int room_id) const; + + // virtual functions + virtual bool IsOpen() const; + virtual bool IsExit() const; + virtual bool IsTransition() const; + virtual bool IsInRoom(int roomID) const; + virtual SubRoom* GetOtherSubRoom(int roomID, int subroomID) const; + + + virtual void WriteToErrorLog() const; + virtual std::string WriteElement() const; // TraVisTo Ausgabe }; #endif /* _TRANSITION_H */ diff --git a/geometry/Wall.cpp b/geometry/Wall.cpp index c0a56433941d45c26b6f52df15aca248152eab50..1c8572853eec63573c3166ab3fccb0c65fd25835 100644 --- a/geometry/Wall.cpp +++ b/geometry/Wall.cpp @@ -32,35 +32,40 @@ using namespace std; Wall ************************************************************/ -Wall::Wall() : Line() { +Wall::Wall() : Line() +{ } -Wall::Wall(const Point& p1, const Point& p2) : Line(p1, p2) { +Wall::Wall(const Point& p1, const Point& p2) : Line(p1, p2) +{ } -Wall::Wall(const Wall& orig) : Line(orig) { +Wall::Wall(const Wall& orig) : Line(orig) +{ } -void Wall::WriteToErrorLog() const { - char tmp[CLENGTH]; - sprintf(tmp, "\t\tWALL: (%f, %f) -- (%f, %f)\n", GetPoint1().GetX(), - GetPoint1().GetY(), GetPoint2().GetX(), GetPoint2().GetY()); - Log->Write(tmp); +void Wall::WriteToErrorLog() const +{ + char tmp[CLENGTH]; + sprintf(tmp, "\t\tWALL: (%f, %f) -- (%f, %f)\n", GetPoint1().GetX(), + GetPoint1().GetY(), GetPoint2().GetX(), GetPoint2().GetY()); + Log->Write(tmp); } -string Wall::Write() const { - string geometry; - char wall[500] = ""; - geometry.append("\t\t<wall>\n"); - sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n", - (GetPoint1().GetX()) * FAKTOR, - (GetPoint1().GetY()) * FAKTOR); - geometry.append(wall); - sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n", - (GetPoint2().GetX()) * FAKTOR, - (GetPoint2().GetY()) * FAKTOR); - geometry.append(wall); - geometry.append("\t\t</wall>\n"); - return geometry; +string Wall::Write() const +{ + string geometry; + char wall[500] = ""; + geometry.append("\t\t<wall>\n"); + sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n", + (GetPoint1().GetX()) * FAKTOR, + (GetPoint1().GetY()) * FAKTOR); + geometry.append(wall); + sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n", + (GetPoint2().GetX()) * FAKTOR, + (GetPoint2().GetY()) * FAKTOR); + geometry.append(wall); + geometry.append("\t\t</wall>\n"); + return geometry; } diff --git a/geometry/Wall.h b/geometry/Wall.h index a1cf286095a50cd14a3b03e311780fd3f2da4fa8..a4815b00a65ab68c6b0b8db886ef2defdc547134 100644 --- a/geometry/Wall.h +++ b/geometry/Wall.h @@ -32,20 +32,20 @@ class Wall : public Line { - public: - Wall(); - Wall(const Point& p1, const Point& p2); - Wall(const Wall& orig); - - /** - * Debug output from the object - */ - void WriteToErrorLog() const; - - /** - * @return a nicely formated string of the object - */ - virtual std::string Write() const; +public: + Wall(); + Wall(const Point& p1, const Point& p2); + Wall(const Wall& orig); + + /** + * Debug output from the object + */ + void WriteToErrorLog() const; + + /** + * @return a nicely formated string of the object + */ + virtual std::string Write() const; }; diff --git a/main.cpp b/main.cpp index 0096e7d0fe2de96b5681059e062f710d90760083..40c66a31b11662350d59af4e8df6e549a656b299 100644 --- a/main.cpp +++ b/main.cpp @@ -1,8 +1,7 @@ /** * @file main.cpp * @author U.Kemloh, A.Portz - * @version 0.4 - * Created on: Apr 20, 2019 + * @version 0.5 * Copyright (C) <2009-2012> * * @section LICENSE @@ -45,57 +44,59 @@ #include "geometry/Building.h" #include "general/ArgumentParser.h" -#include "Simulation.h" +#include "./Simulation.h" -///global unique log variable +/// global unique log variable OutputHandler* Log; -int main(int argc, char **argv) { +int main(int argc, char **argv) +{ - time_t starttime, endtime; + time_t starttime, endtime; - //Log = new FileHandler("./Logfile.dat"); - Log = new STDIOHandler(); + // Log = new FileHandler("./Logfile.dat"); + Log = new STDIOHandler(); - // Parsing the arguments - ArgumentParser* args = new ArgumentParser(); - args->ParseArgs(argc, argv); + // Parsing the arguments - // create and init the simulation engine - // Simulation - time(&starttime); - Log->Write("INFO: \tStart runSimulation()\n"); + ArgumentParser* args = new ArgumentParser(); + args->ParseArgs(argc, argv); - Simulation sim = Simulation(); - sim.InitArgs(args); - int evacTime = sim.RunSimulation(); - Log->Write("\nINFO: \tEnd runSimulation()\n"); - time(&endtime); + // create and init the simulation engine + // Simulation + time(&starttime); + Log->Write("INFO: \tStart runSimulation()\n"); - //some output - double execTime = difftime(endtime, starttime); + Simulation sim = Simulation(); + sim.InitArgs(args); + int evacTime = sim.RunSimulation(); + Log->Write("\nINFO: \tEnd runSimulation()\n"); + time(&endtime); - if(sim.GetPedsNumber()) - Log->Write("\nPedestrians not evacuated [%d] using [%d] threads", sim.GetPedsNumber(), - args->GetMaxOpenMPThreads()); + // some output + double execTime = difftime(endtime, starttime); - Log->Write("\nExec Time [s] : %.2f", execTime); - Log->Write("Evac Time [s] : %d", evacTime); - Log->Write("Real Time Factor : %.2f X", evacTime / execTime); + if (sim.GetPedsNumber()) + Log->Write("\nPedestrians not evacuated [%d] using [%d] threads", + sim.GetPedsNumber(), + args->GetMaxOpenMPThreads()); - //sim.PrintStatistics(); + Log->Write("\nExec Time [s] : %.2f", execTime); + Log->Write("Evac Time [s] : %d", evacTime); + Log->Write("Real Time Factor : %.2f X", evacTime / execTime); - if (NULL == dynamic_cast<STDIOHandler*>(Log)){ - printf("\nExec Time [s] : %.2f\n", execTime); - printf("Evac Time [s] : %d\n", evacTime); - printf("Real Time Factor : %.2f X\n", evacTime / execTime); - } + // sim.PrintStatistics(); + if (NULL == dynamic_cast<STDIOHandler*>(Log)) { + printf("\nExec Time [s] : %.2f\n", execTime); + printf("Evac Time [s] : %d\n", evacTime); + printf("Real Time Factor : %.2f X\n", evacTime / execTime); + } - //do the last cleaning - delete args; - delete Log; + // do the last cleaning + delete args; + delete Log; - return (EXIT_SUCCESS); + return (EXIT_SUCCESS); } diff --git a/math/Distribution.cpp b/math/Distribution.cpp index ca47e1927ead04e9af4748c74599b6aa5f293ff8..fc87f75886dcf5605fb2fd77556d3f5323ebc2d8 100644 --- a/math/Distribution.cpp +++ b/math/Distribution.cpp @@ -1,6 +1,6 @@ /** * File: Distribution.cpp - * + * * Created on 17. February 2011, 15:14 * * @@ -37,80 +37,93 @@ using namespace std; -Distribution::Distribution() { - _mean = 0.; - _sigma = 1.; +Distribution::Distribution() +{ + _mean = 0.; + _sigma = 1.; } -Distribution::Distribution(double m, double s) { - _mean = m; - _sigma = s; +Distribution::Distribution(double m, double s) +{ + _mean = m; + _sigma = s; } -Distribution::Distribution(const Distribution& orig) { - _mean = orig.GetMean(); - _sigma = orig.GetSigma(); +Distribution::Distribution(const Distribution& orig) +{ + _mean = orig.GetMean(); + _sigma = orig.GetSigma(); } -Distribution::~Distribution() { +Distribution::~Distribution() +{ } // Getter-Funktionen -double Distribution::GetMean() const { - return _mean; +double Distribution::GetMean() const +{ + return _mean; } -double Distribution::GetSigma() const { - return _sigma; +double Distribution::GetSigma() const +{ + return _sigma; } /************************************************************* Gauss ************************************************************/ -const vector<double>& Gauss::GetQueue() const { - return _queue; +const vector<double>& Gauss::GetQueue() const +{ + return _queue; } -void Gauss::GetPair() { - double x1 = (double) rand() / (double) RAND_MAX; - double x2 = (double) rand() / (double) RAND_MAX; - double x = GetMean() + sqrt(-2. * GetSigma() * log(x1)) * cos(2. * M_PI * x2); - double y = GetMean() + sqrt(-2. * GetSigma() * log(x1)) * sin(2. * M_PI * x2); +void Gauss::GetPair() +{ + double x1 = (double) rand() / (double) RAND_MAX; + double x2 = (double) rand() / (double) RAND_MAX; + double x = GetMean() + sqrt(-2. * GetSigma() * log(x1)) * cos(2. * M_PI * x2); + double y = GetMean() + sqrt(-2. * GetSigma() * log(x1)) * sin(2. * M_PI * x2); - if (x > J_EPS) { - _queue.push_back(fabs(x)); - } - if (y > J_EPS) { - _queue.push_back(fabs(y)); - } + if (x > J_EPS) { + _queue.push_back(fabs(x)); + } + if (y > J_EPS) { + _queue.push_back(fabs(y)); + } } -Gauss::Gauss() : Distribution() { - _queue = vector<double>(); +Gauss::Gauss() : Distribution() +{ + _queue = vector<double>(); } -Gauss::Gauss(double m, double s) : Distribution(m, s) { - _queue = vector<double>(); +Gauss::Gauss(double m, double s) : Distribution(m, s) +{ + _queue = vector<double>(); } -Gauss::Gauss(const Gauss& orig) : Distribution(orig) { - _queue = orig.GetQueue(); +Gauss::Gauss(const Gauss& orig) : Distribution(orig) +{ + _queue = orig.GetQueue(); } -Gauss::~Gauss() { - _queue.clear(); +Gauss::~Gauss() +{ + _queue.clear(); } -double Gauss::GetRand() { - if (!_queue.size()) { - GetPair(); - } +double Gauss::GetRand() +{ + if (!_queue.size()) { + GetPair(); + } - double r = _queue.back(); // nur ein Wert wird zurück gegeben - _queue.pop_back(); // andere Wert kommt zurück in die Queue - return r; + double r = _queue.back(); // nur ein Wert wird zurück gegeben + _queue.pop_back(); // andere Wert kommt zurück in die Queue + return r; } @@ -118,28 +131,33 @@ double Gauss::GetRand() { Equal ************************************************************/ -Equal::Equal() : Distribution() { +Equal::Equal() : Distribution() +{ } -Equal::Equal(double m, double s) : Distribution(m, s) { +Equal::Equal(double m, double s) : Distribution(m, s) +{ } -Equal::Equal(const Equal& orig) : Distribution(orig) { +Equal::Equal(const Equal& orig) : Distribution(orig) +{ } -Equal::~Equal() { +Equal::~Equal() +{ } // Uniform distribution in [mu-sigma, mu+sigma] -double Equal::GetRand() { - double x; - double mu = GetMean(); - double sigma = GetSigma(); - - do { - x = (double) rand() / (double) RAND_MAX; // [0,1] - x*=2*sigma; // [0, 2*sigma] - x+=(mu-sigma); // [mu-sigma, mu+sigma] - } while( x< mu-sigma || mu+sigma<x); - return x; +double Equal::GetRand() +{ + double x; + double mu = GetMean(); + double sigma = GetSigma(); + + do { + x = (double) rand() / (double) RAND_MAX; // [0,1] + x*=2*sigma; // [0, 2*sigma] + x+=(mu-sigma); // [mu-sigma, mu+sigma] + } while( x< mu-sigma || mu+sigma<x); + return x; } diff --git a/math/Distribution.h b/math/Distribution.h index 3ffc4fbc0872a5e9b6429df446cad129ae243081..c7597296c9311f9663f7e3e82431261206c8e8ec 100644 --- a/math/Distribution.h +++ b/math/Distribution.h @@ -33,65 +33,65 @@ class Distribution { - private: - double _mean; - double _sigma; - public: - Distribution(); - Distribution(double mean, double sigma); - Distribution(const Distribution& orig); - virtual ~Distribution(); - - /** - * @return the mean of the distribution - */ - double GetMean() const; - - /** - * @return the standard deviation of the distribution - */ - double GetSigma() const; - - /** - * @return a random number - */ - virtual double GetRand() =0; // Gibt EINE Zufallszahl zurück +private: + double _mean; + double _sigma; +public: + Distribution(); + Distribution(double mean, double sigma); + Distribution(const Distribution& orig); + virtual ~Distribution(); + + /** + * @return the mean of the distribution + */ + double GetMean() const; + + /** + * @return the standard deviation of the distribution + */ + double GetSigma() const; + + /** + * @return a random number + */ + virtual double GetRand() =0; // Gibt EINE Zufallszahl zurück }; class Gauss : public Distribution { - private: - std::vector<double> _queue; - const std::vector<double>& GetQueue() const; - void GetPair(); - - public: - - Gauss(); - Gauss(double mean, double sigma); - Gauss(const Gauss& orig); - virtual ~Gauss(); - - /** - * @return a number (gauss distributed) - */ - double GetRand(); +private: + std::vector<double> _queue; + const std::vector<double>& GetQueue() const; + void GetPair(); + +public: + + Gauss(); + Gauss(double mean, double sigma); + Gauss(const Gauss& orig); + virtual ~Gauss(); + + /** + * @return a number (gauss distributed) + */ + double GetRand(); }; class Equal : public Distribution { - private: +private: - public: +public: - Equal(); - Equal(double m, double s); - Equal(const Equal& orig); - virtual ~Equal(); + Equal(); + Equal(double m, double s); + Equal(const Equal& orig); + virtual ~Equal(); - /** - * @return a random number (normal distributed) - */ - double GetRand(); + /** + * @return a random number (normal distributed) + */ + double GetRand(); }; #endif /* _DISTRIBUTION_H */ diff --git a/math/ForceModel.cpp b/math/ForceModel.cpp index 0c2964f6583cd94c28089ca2552417c6e4bd8305..932e8eadf186d19b8b1af6257aff63185e33798d 100644 --- a/math/ForceModel.cpp +++ b/math/ForceModel.cpp @@ -20,7 +20,7 @@ * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. * * @section DESCRIPTION - * Implementation of the GCFM and the Gompertz model + * Implementation of the GCFM and the Gompertz model * * */ @@ -28,7 +28,7 @@ #include "ForceModel.h" #include "../routing/DirectionStrategy.h" #include "../mpi/LCGrid.h" -#include "../pedestrian/Pedestrian.h" +#include "../pedestrian/Pedestrian.h" #ifdef _OPENMP @@ -42,11 +42,13 @@ using namespace std; -ForceModel::ForceModel() { +ForceModel::ForceModel() +{ } -ForceModel::~ForceModel() { +ForceModel::~ForceModel() +{ } /************************************************************ @@ -54,145 +56,147 @@ ForceModel::~ForceModel() { ************************************************************/ -inline Point GCFMModel::ForceDriv(Pedestrian* ped, Room* room) const { - const Point& target = _direction->GetTarget(room, ped); - Point F_driv; - const Point& pos = ped->GetPos(); - double dist = ped->GetExitLine()->DistTo(pos); - - - if (dist > J_EPS_GOAL) { - const Point& v0 = ped->GetV0(target); - //printf("MC v0= [%.2f %.2f]\n", v0.GetX(), v0.GetY()); - //fprintf(stderr, "%.2f %.2f %.2f %.2f %f %f\n", v0.GetX(), v0.GetY(), pos.GetX(), pos.GetY(), target.GetX(), target.GetY()); - F_driv = ((v0 * ped->GetV0Norm() - ped->GetV()) * ped->GetMass()) / ped->GetTau(); - } else { - const Point& v0 = ped->GetV0(); - //fprintf(stderr, "%.2f %.2f %.2f %.2f %f %f\n", v0.GetX(), v0.GetY(), pos.GetX(), pos.GetY(), target.GetX(), target.GetY()); - F_driv = ((v0 * ped->GetV0Norm() - ped->GetV()) * ped->GetMass()) / ped->GetTau(); - } - return F_driv; +inline Point GCFMModel::ForceDriv(Pedestrian* ped, Room* room) const +{ + const Point& target = _direction->GetTarget(room, ped); + Point F_driv; + const Point& pos = ped->GetPos(); + double dist = ped->GetExitLine()->DistTo(pos); + + + if (dist > J_EPS_GOAL) { + const Point& v0 = ped->GetV0(target); + //printf("MC v0= [%.2f %.2f]\n", v0.GetX(), v0.GetY()); + //fprintf(stderr, "%.2f %.2f %.2f %.2f %f %f\n", v0.GetX(), v0.GetY(), pos.GetX(), pos.GetY(), target.GetX(), target.GetY()); + F_driv = ((v0 * ped->GetV0Norm() - ped->GetV()) * ped->GetMass()) / ped->GetTau(); + } else { + const Point& v0 = ped->GetV0(); + //fprintf(stderr, "%.2f %.2f %.2f %.2f %f %f\n", v0.GetX(), v0.GetY(), pos.GetX(), pos.GetY(), target.GetX(), target.GetY()); + F_driv = ((v0 * ped->GetV0Norm() - ped->GetV()) * ped->GetMass()) / ped->GetTau(); + } + return F_driv; } -Point GCFMModel::ForceRepPed(Pedestrian* ped1, Pedestrian* ped2) const { - - Point F_rep; - // x- and y-coordinate of the distance between p1 and p2 - Point distp12 = ped2->GetPos() - ped1->GetPos(); - const Point& vp1 = ped1->GetV(); // v Ped1 - const Point& vp2 = ped2->GetV(); // v Ped2 - Point ep12; // x- and y-coordinate of the normalized vector between p1 and p2 - double tmp, tmp2; - double v_ij; - double K_ij; - //double r1, r2; - double nom; //nominator of Frep - double px; // hermite Interpolation value - const JEllipse& E1 = ped1->GetEllipse(); - const JEllipse& E2 = ped2->GetEllipse(); - double distsq; - double dist_eff = E1.EffectiveDistanceToEllipse(E2, &distsq); - - - // smax dist_intpol_left dist_intpol_right dist_eff_max - // ----|-------------|--------------------------|--------------|---- - // 5 | 4 | 3 | 2 | 1 - - // If the pedestrian is outside the cutoff distance, the force is zero. - if (dist_eff >= _distEffMaxPed) { - F_rep = Point(0.0, 0.0); - return F_rep; - } - //Point AP1inE1 = Point(E1.GetXp(), 0); // ActionPoint von E1 in Koordinaten von E1 - //Point AP2inE2 = Point(E2.GetXp(), 0); // ActionPoint von E2 in Koordinaten von E2 - // ActionPoint von E1 in Koordinaten von E2 (transformieren) - //Point AP1inE2 = AP1inE1.CoordTransToEllipse(E2.GetCenter(), E2.GetCosPhi(), E2.GetSinPhi()); - // ActionPoint von E2 in Koordinaten von E1 (transformieren) - //Point AP2inE1 = AP2inE2.CoordTransToEllipse(E1.GetCenter(), E1.GetCosPhi(), E1.GetSinPhi()); - //r1 = (AP1inE1 - E1.PointOnEllipse(AP2inE1)).Norm(); - //r2 = (AP2inE2 - E2.PointOnEllipse(AP1inE2)).Norm(); - - //%------- Free parameter -------------- - Point p1, p2; // "Normale" Koordinaten - double mindist; - - - p1 = Point(E1.GetXp(), 0).CoordTransToCart(E1.GetCenter(), E1.GetCosPhi(), E1.GetSinPhi()); - p2 = Point(E2.GetXp(), 0).CoordTransToCart(E2.GetCenter(), E2.GetCosPhi(), E2.GetSinPhi()); - distp12 = p2 - p1; - //mindist = E1.MinimumDistanceToEllipse(E2); //ONE - mindist = 0.5; //for performance reasons, it is assumed that this distance is about 50 cm - double dist_intpol_left = mindist + _intp_widthPed; // lower cut-off for Frep (modCFM) - double dist_intpol_right = _distEffMaxPed - _intp_widthPed; //upper cut-off for Frep (modCFM) - double smax = mindist - _intp_widthPed; //max overlapping - double f = 0.0f, f1 = 0.0f; //function value and its derivative at the interpolation point' - - //todo: runtime normsquare? - if (distp12.Norm() >= J_EPS) { - ep12 = distp12.Normalized(); - - } else { - Log->Write("ERROR: \tin GCFMModel::forcePedPed() ep12 kann nicht berechnet werden!!!\n"); - Log->Write("ERROR:\t fix this as soon as possible"); - return F_rep; // FIXME: should never happen - exit(0); - - } - // calculate the parameter (whatever dist is) - tmp = (vp1 - vp2).ScalarP(ep12); // < v_ij , e_ij > - v_ij = 0.5 * (tmp + fabs(tmp)); - tmp2 = vp1.ScalarP(ep12); // < v_i , e_ij > - - //todo: runtime normsquare? - if (vp1.Norm() < J_EPS) { // if(norm(v_i)==0) - K_ij = 0; - } else { - double bla = tmp2 + fabs(tmp2); - K_ij = 0.25 * bla * bla / vp1.ScalarP(vp1); //squared - - if (K_ij < J_EPS * J_EPS) { - F_rep = Point(0.0, 0.0); - return F_rep; - } - } - nom = _nuPed * ped1->GetV0Norm() + v_ij; // Nu: 0=CFM, 0.28=modifCFM; - nom *= nom; - - K_ij = sqrt(K_ij); - if (dist_eff <= smax) { //5 - f = -ped1->GetMass() * K_ij * nom / dist_intpol_left; - F_rep = ep12 * _maxfPed * f; - return F_rep; - } - - // smax dist_intpol_left dist_intpol_right dist_eff_max - // ----|-------------|--------------------------|--------------|---- - // 5 | 4 | 3 | 2 | 1 - - if (dist_eff >= dist_intpol_right) { //2 - f = -ped1->GetMass() * K_ij * nom / dist_intpol_right; // abs(NR-Dv(i)+Sa) - f1 = -f / dist_intpol_right; - px = hermite_interp(dist_eff, dist_intpol_right, _distEffMaxPed, f, 0, f1, 0); - F_rep = ep12 * px; - } else if (dist_eff >= dist_intpol_left) { //3 - f = -ped1->GetMass() * K_ij * nom / fabs(dist_eff); // abs(NR-Dv(i)+Sa) - F_rep = ep12 * f; - } else {//4 - f = -ped1->GetMass() * K_ij * nom / dist_intpol_left; - f1 = -f / dist_intpol_left; - px = hermite_interp(dist_eff, smax, dist_intpol_left, _maxfPed*f, f, 0, f1); - F_rep = ep12 * px; - } - if (F_rep.GetX() != F_rep.GetX() || F_rep.GetY() != F_rep.GetY()) { - char tmp[CLENGTH]; - sprintf(tmp, "\nNAN return ----> p1=%d p2=%d Frepx=%f, Frepy=%f\n", ped1->GetID(), - ped2->GetID(), F_rep.GetX(), F_rep.GetY()); - Log->Write(tmp); - Log->Write("ERROR:\t fix this as soon as possible"); - return Point(0,0); // FIXME: should never happen - exit(0); - } - return F_rep; +Point GCFMModel::ForceRepPed(Pedestrian* ped1, Pedestrian* ped2) const +{ + + Point F_rep; + // x- and y-coordinate of the distance between p1 and p2 + Point distp12 = ped2->GetPos() - ped1->GetPos(); + const Point& vp1 = ped1->GetV(); // v Ped1 + const Point& vp2 = ped2->GetV(); // v Ped2 + Point ep12; // x- and y-coordinate of the normalized vector between p1 and p2 + double tmp, tmp2; + double v_ij; + double K_ij; + //double r1, r2; + double nom; //nominator of Frep + double px; // hermite Interpolation value + const JEllipse& E1 = ped1->GetEllipse(); + const JEllipse& E2 = ped2->GetEllipse(); + double distsq; + double dist_eff = E1.EffectiveDistanceToEllipse(E2, &distsq); + + + // smax dist_intpol_left dist_intpol_right dist_eff_max + // ----|-------------|--------------------------|--------------|---- + // 5 | 4 | 3 | 2 | 1 + + // If the pedestrian is outside the cutoff distance, the force is zero. + if (dist_eff >= _distEffMaxPed) { + F_rep = Point(0.0, 0.0); + return F_rep; + } + //Point AP1inE1 = Point(E1.GetXp(), 0); // ActionPoint von E1 in Koordinaten von E1 + //Point AP2inE2 = Point(E2.GetXp(), 0); // ActionPoint von E2 in Koordinaten von E2 + // ActionPoint von E1 in Koordinaten von E2 (transformieren) + //Point AP1inE2 = AP1inE1.CoordTransToEllipse(E2.GetCenter(), E2.GetCosPhi(), E2.GetSinPhi()); + // ActionPoint von E2 in Koordinaten von E1 (transformieren) + //Point AP2inE1 = AP2inE2.CoordTransToEllipse(E1.GetCenter(), E1.GetCosPhi(), E1.GetSinPhi()); + //r1 = (AP1inE1 - E1.PointOnEllipse(AP2inE1)).Norm(); + //r2 = (AP2inE2 - E2.PointOnEllipse(AP1inE2)).Norm(); + + //%------- Free parameter -------------- + Point p1, p2; // "Normale" Koordinaten + double mindist; + + + p1 = Point(E1.GetXp(), 0).CoordTransToCart(E1.GetCenter(), E1.GetCosPhi(), E1.GetSinPhi()); + p2 = Point(E2.GetXp(), 0).CoordTransToCart(E2.GetCenter(), E2.GetCosPhi(), E2.GetSinPhi()); + distp12 = p2 - p1; + //mindist = E1.MinimumDistanceToEllipse(E2); //ONE + mindist = 0.5; //for performance reasons, it is assumed that this distance is about 50 cm + double dist_intpol_left = mindist + _intp_widthPed; // lower cut-off for Frep (modCFM) + double dist_intpol_right = _distEffMaxPed - _intp_widthPed; //upper cut-off for Frep (modCFM) + double smax = mindist - _intp_widthPed; //max overlapping + double f = 0.0f, f1 = 0.0f; //function value and its derivative at the interpolation point' + + //todo: runtime normsquare? + if (distp12.Norm() >= J_EPS) { + ep12 = distp12.Normalized(); + + } else { + Log->Write("ERROR: \tin GCFMModel::forcePedPed() ep12 kann nicht berechnet werden!!!\n"); + Log->Write("ERROR:\t fix this as soon as possible"); + return F_rep; // FIXME: should never happen + exit(0); + + } + // calculate the parameter (whatever dist is) + tmp = (vp1 - vp2).ScalarP(ep12); // < v_ij , e_ij > + v_ij = 0.5 * (tmp + fabs(tmp)); + tmp2 = vp1.ScalarP(ep12); // < v_i , e_ij > + + //todo: runtime normsquare? + if (vp1.Norm() < J_EPS) { // if(norm(v_i)==0) + K_ij = 0; + } else { + double bla = tmp2 + fabs(tmp2); + K_ij = 0.25 * bla * bla / vp1.ScalarP(vp1); //squared + + if (K_ij < J_EPS * J_EPS) { + F_rep = Point(0.0, 0.0); + return F_rep; + } + } + nom = _nuPed * ped1->GetV0Norm() + v_ij; // Nu: 0=CFM, 0.28=modifCFM; + nom *= nom; + + K_ij = sqrt(K_ij); + if (dist_eff <= smax) { //5 + f = -ped1->GetMass() * K_ij * nom / dist_intpol_left; + F_rep = ep12 * _maxfPed * f; + return F_rep; + } + + // smax dist_intpol_left dist_intpol_right dist_eff_max + // ----|-------------|--------------------------|--------------|---- + // 5 | 4 | 3 | 2 | 1 + + if (dist_eff >= dist_intpol_right) { //2 + f = -ped1->GetMass() * K_ij * nom / dist_intpol_right; // abs(NR-Dv(i)+Sa) + f1 = -f / dist_intpol_right; + px = hermite_interp(dist_eff, dist_intpol_right, _distEffMaxPed, f, 0, f1, 0); + F_rep = ep12 * px; + } else if (dist_eff >= dist_intpol_left) { //3 + f = -ped1->GetMass() * K_ij * nom / fabs(dist_eff); // abs(NR-Dv(i)+Sa) + F_rep = ep12 * f; + } else {//4 + f = -ped1->GetMass() * K_ij * nom / dist_intpol_left; + f1 = -f / dist_intpol_left; + px = hermite_interp(dist_eff, smax, dist_intpol_left, _maxfPed*f, f, 0, f1); + F_rep = ep12 * px; + } + if (F_rep.GetX() != F_rep.GetX() || F_rep.GetY() != F_rep.GetY()) { + char tmp[CLENGTH]; + sprintf(tmp, "\nNAN return ----> p1=%d p2=%d Frepx=%f, Frepy=%f\n", ped1->GetID(), + ped2->GetID(), F_rep.GetX(), F_rep.GetY()); + Log->Write(tmp); + Log->Write("ERROR:\t fix this as soon as possible"); + return Point(0,0); // FIXME: should never happen + exit(0); + } + return F_rep; } /* abstoßende Kraft zwischen ped und subroom @@ -203,72 +207,73 @@ Point GCFMModel::ForceRepPed(Pedestrian* ped1, Pedestrian* ped2) const { * - Vektor(x,y) mit Summe aller abstoßenden Kräfte im SubRoom * */ -inline Point GCFMModel::ForceRepRoom(Pedestrian* ped, SubRoom* subroom) const { - Point f = Point(0., 0.); - //first the walls - - const vector<Wall>& walls = subroom->GetAllWalls(); - for (int i = 0; i < subroom->GetNumberOfWalls(); i++) { - f = f + ForceRepWall(ped, walls[i]); - } - - //then the obstacles - const vector<Obstacle*>& obstacles = subroom->GetAllObstacles(); - for(unsigned int obs=0;obs<obstacles.size();++obs){ - const vector<Wall>& walls = obstacles[obs]->GetAllWalls(); - for (unsigned int i = 0; i < walls.size(); i++) { - f = f + ForceRepWall(ped, walls[i]); - } - } - - //eventually crossings - const vector<Crossing*>& crossings = subroom->GetAllCrossings(); - for (unsigned int i = 0; i < crossings.size(); i++) { - //Crossing* goal=crossings[i]; - //int uid1= goal->GetUniqueID(); - //int uid2=ped->GetExitIndex(); - // ignore my transition - //if (uid1 != uid2) { - // f = f + ForceRepWall(ped,*((Wall*)goal)); - //} - } - - // and finally the closed doors or doors that are not my destination - const vector<Transition*>& transitions = subroom->GetAllTransitions(); - for (unsigned int i = 0; i < transitions.size(); i++) { - Transition* goal=transitions[i]; - int uid1= goal->GetUniqueID(); - int uid2=ped->GetExitIndex(); - // ignore my transition consider closed doors - //closed doors are considered as wall - - if((uid1 != uid2) || (goal->IsOpen()==false )) { - f = f + ForceRepWall(ped,*((Wall*)goal)); - } - } - - return f; +inline Point GCFMModel::ForceRepRoom(Pedestrian* ped, SubRoom* subroom) const +{ + Point f = Point(0., 0.); + //first the walls + + const vector<Wall>& walls = subroom->GetAllWalls(); + for (int i = 0; i < subroom->GetNumberOfWalls(); i++) { + f = f + ForceRepWall(ped, walls[i]); + } + + //then the obstacles + const vector<Obstacle*>& obstacles = subroom->GetAllObstacles(); + for(unsigned int obs=0; obs<obstacles.size(); ++obs) { + const vector<Wall>& walls = obstacles[obs]->GetAllWalls(); + for (unsigned int i = 0; i < walls.size(); i++) { + f = f + ForceRepWall(ped, walls[i]); + } + } + + //eventually crossings + const vector<Crossing*>& crossings = subroom->GetAllCrossings(); + for (unsigned int i = 0; i < crossings.size(); i++) { + //Crossing* goal=crossings[i]; + //int uid1= goal->GetUniqueID(); + //int uid2=ped->GetExitIndex(); + // ignore my transition + //if (uid1 != uid2) { + // f = f + ForceRepWall(ped,*((Wall*)goal)); + //} + } + + // and finally the closed doors or doors that are not my destination + const vector<Transition*>& transitions = subroom->GetAllTransitions(); + for (unsigned int i = 0; i < transitions.size(); i++) { + Transition* goal=transitions[i]; + int uid1= goal->GetUniqueID(); + int uid2=ped->GetExitIndex(); + // ignore my transition consider closed doors + //closed doors are considered as wall + + if((uid1 != uid2) || (goal->IsOpen()==false )) { + f = f + ForceRepWall(ped,*((Wall*)goal)); + } + } + + return f; } -inline Point GCFMModel::ForceRepWall(Pedestrian* ped, const Wall& w) const { - Point F = Point(0.0, 0.0); - Point pt = w.ShortestPoint(ped->GetPos()); - double wlen = w.LengthSquare(); - - if (wlen < 0.01) { // ignore walls smaller than 10 cm - return F; - } - // Kraft soll nur orthgonal wirken - // ??? - if (fabs((w.GetPoint1() - w.GetPoint2()).ScalarP(ped->GetPos() - pt)) > J_EPS) - { - return F; - } - //double mind = ped->GetEllipse().MinimumDistanceToLine(w); - double mind = 0.5; //for performance reasons this distance is assumed to be constant - double vn = w.NormalComp(ped->GetV()); //normal component of the velocity on the wall - return ForceRepStatPoint(ped, pt, mind, vn); //line --> l != 0 +inline Point GCFMModel::ForceRepWall(Pedestrian* ped, const Wall& w) const +{ + Point F = Point(0.0, 0.0); + Point pt = w.ShortestPoint(ped->GetPos()); + double wlen = w.LengthSquare(); + + if (wlen < 0.01) { // ignore walls smaller than 10 cm + return F; + } + // Kraft soll nur orthgonal wirken + // ??? + if (fabs((w.GetPoint1() - w.GetPoint2()).ScalarP(ped->GetPos() - pt)) > J_EPS) { + return F; + } + //double mind = ped->GetEllipse().MinimumDistanceToLine(w); + double mind = 0.5; //for performance reasons this distance is assumed to be constant + double vn = w.NormalComp(ped->GetV()); //normal component of the velocity on the wall + return ForceRepStatPoint(ped, pt, mind, vn); //line --> l != 0 } /* abstoßende Punktkraft zwischen ped und Punkt p @@ -281,285 +286,301 @@ inline Point GCFMModel::ForceRepWall(Pedestrian* ped, const Wall& w) const { * - Vektor(x,y) mit abstoßender Kraft * */ //TODO: use effective DistanceToEllipse and simplify this function. -Point GCFMModel::ForceRepStatPoint(Pedestrian* ped, const Point& p, double l, double vn) const { - Point F_rep = Point(0.0, 0.0); - const Point& v = ped->GetV(); - Point dist = p - ped->GetPos(); // x- and y-coordinate of the distance between ped and p - double d = dist.Norm(); // distance between the centre of ped and point p - Point e_ij; // x- and y-coordinate of the normalized vector between ped and p - double K_ij; - double tmp; - double bla; - Point r; - Point pinE; // vorher x1, y1 - const JEllipse& E = ped->GetEllipse(); - - if (d < J_EPS) - return Point(0.0, 0.0); - e_ij = dist / d; - tmp = v.ScalarP(e_ij); // < v_i , e_ij >; - bla = (tmp + fabs(tmp)); - if (!bla) // Fussgaenger nicht im Sichtfeld - return Point(0.0, 0.0); - if (fabs(v.GetX()) < J_EPS && fabs(v.GetY()) < J_EPS) // v==0) - return Point(0.0, 0.0); - K_ij = 0.5 * bla / v.Norm(); // K_ij - // Punkt auf der Ellipse - pinE = p.CoordTransToEllipse(E.GetCenter(), E.GetCosPhi(), E.GetSinPhi()); - // Punkt auf der Ellipse - r = E.PointOnEllipse(pinE); - //interpolierte Kraft - F_rep = ForceInterpolation(ped->GetV0Norm(), K_ij, e_ij, vn, d, (r - E.GetCenter()).Norm(), l); - return F_rep; +Point GCFMModel::ForceRepStatPoint(Pedestrian* ped, const Point& p, double l, double vn) const +{ + Point F_rep = Point(0.0, 0.0); + const Point& v = ped->GetV(); + Point dist = p - ped->GetPos(); // x- and y-coordinate of the distance between ped and p + double d = dist.Norm(); // distance between the centre of ped and point p + Point e_ij; // x- and y-coordinate of the normalized vector between ped and p + double K_ij; + double tmp; + double bla; + Point r; + Point pinE; // vorher x1, y1 + const JEllipse& E = ped->GetEllipse(); + + if (d < J_EPS) + return Point(0.0, 0.0); + e_ij = dist / d; + tmp = v.ScalarP(e_ij); // < v_i , e_ij >; + bla = (tmp + fabs(tmp)); + if (!bla) // Fussgaenger nicht im Sichtfeld + return Point(0.0, 0.0); + if (fabs(v.GetX()) < J_EPS && fabs(v.GetY()) < J_EPS) // v==0) + return Point(0.0, 0.0); + K_ij = 0.5 * bla / v.Norm(); // K_ij + // Punkt auf der Ellipse + pinE = p.CoordTransToEllipse(E.GetCenter(), E.GetCosPhi(), E.GetSinPhi()); + // Punkt auf der Ellipse + r = E.PointOnEllipse(pinE); + //interpolierte Kraft + F_rep = ForceInterpolation(ped->GetV0Norm(), K_ij, e_ij, vn, d, (r - E.GetCenter()).Norm(), l); + return F_rep; } -Point GCFMModel::ForceInterpolation(double v0, double K_ij, const Point& e, double vn, double d, double r, double l) const { - Point F_rep; - double nominator = _nuWall * v0 + vn; - nominator *= nominator*K_ij; - double f = 0, f1 = 0; //function value and its derivative at the interpolation point - //BEGIN ------- interpolation parameter - double smax = l - _intp_widthWall; // max overlapping radius - double dist_intpol_left = l + _intp_widthWall; //r_eps - double dist_intpol_right = _distEffMaxWall - _intp_widthWall; - //END ------- interpolation parameter - - double dist_eff = d - r; - - // smax dist_intpol_left dist_intpol_right dist_eff_max - // ----|-------------|--------------------------|--------------|---- - // 5 | 4 | 3 | 2 | 1 - - double px = 0; //value of the interpolated function - double tmp1 = _distEffMaxWall; - double tmp2 = dist_intpol_right; - double tmp3 = dist_intpol_left; - double tmp5 = smax + r; - - if (dist_eff >= tmp1) { // 1 - //F_rep = Point(0.0, 0.0); - return F_rep; - } - - if (dist_eff <= tmp5) { // 5 - F_rep = e * (-_maxfWall); - return F_rep; - } - - if (dist_eff > tmp2) { //2 - f = -nominator / dist_intpol_right; - f1 = -f / dist_intpol_right; // nominator / (dist_intpol_right^2) = derivativ of f - px = hermite_interp(dist_eff, dist_intpol_right, _distEffMaxWall, f, 0, f1, 0); - F_rep = e * px; - } else if (dist_eff >= tmp3) { //3 - f = -nominator / fabs(dist_eff); //devided by abs f the effective distance - F_rep = e * f; - } else { //4 d > smax FIXME - f = -nominator / dist_intpol_left; - f1 = -f / dist_intpol_left; - px = hermite_interp(dist_eff, smax, dist_intpol_left, _maxfWall*f, f, 0, f1); - F_rep = e * px; - } - return F_rep; +Point GCFMModel::ForceInterpolation(double v0, double K_ij, const Point& e, double vn, double d, double r, double l) const +{ + Point F_rep; + double nominator = _nuWall * v0 + vn; + nominator *= nominator*K_ij; + double f = 0, f1 = 0; //function value and its derivative at the interpolation point + //BEGIN ------- interpolation parameter + double smax = l - _intp_widthWall; // max overlapping radius + double dist_intpol_left = l + _intp_widthWall; //r_eps + double dist_intpol_right = _distEffMaxWall - _intp_widthWall; + //END ------- interpolation parameter + + double dist_eff = d - r; + + // smax dist_intpol_left dist_intpol_right dist_eff_max + // ----|-------------|--------------------------|--------------|---- + // 5 | 4 | 3 | 2 | 1 + + double px = 0; //value of the interpolated function + double tmp1 = _distEffMaxWall; + double tmp2 = dist_intpol_right; + double tmp3 = dist_intpol_left; + double tmp5 = smax + r; + + if (dist_eff >= tmp1) { // 1 + //F_rep = Point(0.0, 0.0); + return F_rep; + } + + if (dist_eff <= tmp5) { // 5 + F_rep = e * (-_maxfWall); + return F_rep; + } + + if (dist_eff > tmp2) { //2 + f = -nominator / dist_intpol_right; + f1 = -f / dist_intpol_right; // nominator / (dist_intpol_right^2) = derivativ of f + px = hermite_interp(dist_eff, dist_intpol_right, _distEffMaxWall, f, 0, f1, 0); + F_rep = e * px; + } else if (dist_eff >= tmp3) { //3 + f = -nominator / fabs(dist_eff); //devided by abs f the effective distance + F_rep = e * f; + } else { //4 d > smax FIXME + f = -nominator / dist_intpol_left; + f1 = -f / dist_intpol_left; + px = hermite_interp(dist_eff, smax, dist_intpol_left, _maxfWall*f, f, 0, f1); + F_rep = e * px; + } + return F_rep; } GCFMModel::GCFMModel(DirectionStrategy* dir, double nuped, double nuwall, double dist_effPed, - double dist_effWall, double intp_widthped, double intp_widthwall, double maxfped, - double maxfwall) { - _direction = dir; - _nuPed = nuped; - _nuWall = nuwall; - _intp_widthPed = intp_widthped; - _intp_widthWall = intp_widthwall; - _maxfPed = maxfped; - _maxfWall = maxfwall; - _distEffMaxPed = dist_effPed; - _distEffMaxWall = dist_effWall; + double dist_effWall, double intp_widthped, double intp_widthwall, double maxfped, + double maxfwall) +{ + _direction = dir; + _nuPed = nuped; + _nuWall = nuwall; + _intp_widthPed = intp_widthped; + _intp_widthWall = intp_widthwall; + _maxfPed = maxfped; + _maxfWall = maxfwall; + _distEffMaxPed = dist_effPed; + _distEffMaxWall = dist_effWall; } -GCFMModel::~GCFMModel(void) { +GCFMModel::~GCFMModel(void) +{ } // Getter-Funktionen -DirectionStrategy* GCFMModel::GetDirection() const { - return _direction; +DirectionStrategy* GCFMModel::GetDirection() const +{ + return _direction; } -double GCFMModel::GetNuPed() const { - return _nuPed; +double GCFMModel::GetNuPed() const +{ + return _nuPed; } -double GCFMModel::GetNuWall() const { - return _nuWall; +double GCFMModel::GetNuWall() const +{ + return _nuWall; } -double GCFMModel::GetIntpWidthPed() const { - return _intp_widthPed; +double GCFMModel::GetIntpWidthPed() const +{ + return _intp_widthPed; } -double GCFMModel::GetIntpWidthWall() const { - return _intp_widthWall; +double GCFMModel::GetIntpWidthWall() const +{ + return _intp_widthWall; } -double GCFMModel::GetMaxFPed() const { - return _maxfPed; +double GCFMModel::GetMaxFPed() const +{ + return _maxfPed; } -double GCFMModel::GetMaxFWall() const { - return _maxfWall; +double GCFMModel::GetMaxFWall() const +{ + return _maxfWall; } -double GCFMModel::GetDistEffMaxPed() const { - return _distEffMaxPed; +double GCFMModel::GetDistEffMaxPed() const +{ + return _distEffMaxPed; } -double GCFMModel::GetDistEffMaxWall() const { - return _distEffMaxWall; +double GCFMModel::GetDistEffMaxWall() const +{ + return _distEffMaxWall; } -string GCFMModel::writeParameter() const { - string rueck; - char tmp[CLENGTH]; - - sprintf(tmp, "\t\tNu: \t\tPed: %f \tWall: %f\n", _nuPed, _nuWall); - rueck.append(tmp); - sprintf(tmp, "\t\tInterp. Width: \tPed: %f \tWall: %f\n", _intp_widthPed, _intp_widthWall); - rueck.append(tmp); - sprintf(tmp, "\t\tMaxF: \t\tPed: %f \tWall: %f\n", _maxfPed, _maxfWall); - rueck.append(tmp); - sprintf(tmp, "\t\tDistEffMax: \tPed: %f \tWall: %f\n", _distEffMaxPed, _distEffMaxWall); - rueck.append(tmp); - - return rueck; +string GCFMModel::writeParameter() const +{ + string rueck; + char tmp[CLENGTH]; + + sprintf(tmp, "\t\tNu: \t\tPed: %f \tWall: %f\n", _nuPed, _nuWall); + rueck.append(tmp); + sprintf(tmp, "\t\tInterp. Width: \tPed: %f \tWall: %f\n", _intp_widthPed, _intp_widthWall); + rueck.append(tmp); + sprintf(tmp, "\t\tMaxF: \t\tPed: %f \tWall: %f\n", _maxfPed, _maxfWall); + rueck.append(tmp); + sprintf(tmp, "\t\tDistEffMax: \tPed: %f \tWall: %f\n", _distEffMaxPed, _distEffMaxWall); + rueck.append(tmp); + + return rueck; } // virtuelle Funktionen void GCFMModel::CalculateForce(double time, vector< Point >& result_acc, Building* building, - int roomID, int subroomID) const { + int roomID, int subroomID) const +{ - printf("CalculateForce is not working: you should not use this function"); - exit(0); + printf("CalculateForce is not working: you should not use this function"); + exit(0); } /** * implementation of Linked-cell combined with openMP */ -void GCFMModel::CalculateForceLC(double time, double tip1, Building* building) const { - double delta = 0.5; - double h = tip1 - time; - // collect all pedestrians in the simulation. - const vector< Pedestrian* >& allPeds = building->GetAllPedestrians(); - - unsigned int nSize = allPeds.size(); - - int nThreads = omp_get_max_threads(); - - // check if worth sharing the work - if (nSize < 20) nThreads = 1; - int partSize = nSize / nThreads; - -#pragma omp parallel default(shared) num_threads(nThreads) - { - vector< Point > result_acc = vector<Point > (); - result_acc.reserve(2200); - - const int threadID = omp_get_thread_num(); - - int start = threadID*partSize; - int end = (threadID + 1) * partSize - 1; - if ((threadID == nThreads - 1)) end = nSize - 1; - - for (int p = start; p <= end; ++p) { - - Pedestrian* ped = allPeds[p]; - Room* room = building->GetRoom(ped->GetRoomID()); - SubRoom* subroom = room->GetSubRoom(ped->GetSubRoomID()); - if(subroom->GetType()=="cellular") continue; - - double normVi = ped->GetV().ScalarP(ped->GetV()); - double tmp = (ped->GetV0Norm() + delta) * (ped->GetV0Norm() + delta); - if (normVi > tmp && ped->GetV0Norm() > 0) { - fprintf(stderr, "GCFMModel::calculateForce() WARNING: actual velocity (%f) of iped %d " - "is bigger than desired velocity (%f) at time: %fs\n", - sqrt(normVi), ped->GetID(), ped->GetV0Norm(), time); - - // remove the pedestrian and abort - for(int p=0;p<subroom->GetNumberOfPedestrians();p++){ - if (subroom->GetPedestrian(p)->GetID()==ped->GetID()){ - subroom->DeletePedestrian(p); - break; - } - } - - building->DeletePedFromSim(ped); - Log->Write("\tCRITICAL: one ped was removed due to high velocity"); - - // continue; - exit(EXIT_FAILURE); - } - - Point F_rep; - vector<Pedestrian*> neighbours; - building->GetGrid()->GetNeighbourhood(ped,neighbours); - - int nSize=neighbours.size(); - for (int i = 0; i < nSize; i++) { - Pedestrian* ped1 = neighbours[i]; - //if they are in the same subroom - if (ped->GetUniqueRoomID() == ped1->GetUniqueRoomID()) { - F_rep = F_rep + ForceRepPed(ped, ped1); - } else { - // or in neighbour subrooms - SubRoom* sb2=building->GetRoom(ped1->GetRoomID())->GetSubRoom(ped1->GetSubRoomID()); - if(subroom->IsDirectlyConnectedWith(sb2)){ - F_rep = F_rep + ForceRepPed(ped, ped1); - } - } - }//for peds - - //repulsive forces to the walls and transitions that are not my target - Point repwall = ForceRepRoom(allPeds[p], subroom); - Point fd = ForceDriv(ped, room); - // Point acc = (ForceDriv(ped, room) + F_rep + repwall) / ped->GetMass(); - Point acc = (fd + F_rep + repwall) / ped->GetMass(); - result_acc.push_back(acc); - } - - //#pragma omp barrier - // update - for (int p = start; p <= end; ++p) { - Pedestrian* ped = allPeds[p]; - Point v_neu = ped->GetV() + result_acc[p - start] * h; - Point pos_neu = ped->GetPos() + v_neu * h; - - Room* room = building->GetRoom(ped->GetRoomID()); - SubRoom* subroom = room->GetSubRoom(ped->GetSubRoomID()); - if(subroom->GetType()=="cellular") continue; - - //Jam is based on the current velocity - if (v_neu.Norm() >= J_EPS_V){ - ped->ResetTimeInJam(); - }else{ - ped->UpdateTimeInJam(); - } - - ped->SetPos(pos_neu); - ped->SetV(v_neu); - ped->SetPhiPed(); - } - - }//end parallel - - //update the CA Model - //UpdateCellularModel(building); +void GCFMModel::CalculateForceLC(double time, double tip1, Building* building) const +{ + double delta = 0.5; + double h = tip1 - time; + // collect all pedestrians in the simulation. + const vector< Pedestrian* >& allPeds = building->GetAllPedestrians(); + + unsigned int nSize = allPeds.size(); + + int nThreads = omp_get_max_threads(); + + // check if worth sharing the work + if (nSize < 20) nThreads = 1; + int partSize = nSize / nThreads; + + #pragma omp parallel default(shared) num_threads(nThreads) + { + vector< Point > result_acc = vector<Point > (); + result_acc.reserve(2200); + + const int threadID = omp_get_thread_num(); + + int start = threadID*partSize; + int end = (threadID + 1) * partSize - 1; + if ((threadID == nThreads - 1)) end = nSize - 1; + + for (int p = start; p <= end; ++p) { + + Pedestrian* ped = allPeds[p]; + Room* room = building->GetRoom(ped->GetRoomID()); + SubRoom* subroom = room->GetSubRoom(ped->GetSubRoomID()); + if(subroom->GetType()=="cellular") continue; + + double normVi = ped->GetV().ScalarP(ped->GetV()); + double tmp = (ped->GetV0Norm() + delta) * (ped->GetV0Norm() + delta); + if (normVi > tmp && ped->GetV0Norm() > 0) { + fprintf(stderr, "GCFMModel::calculateForce() WARNING: actual velocity (%f) of iped %d " + "is bigger than desired velocity (%f) at time: %fs\n", + sqrt(normVi), ped->GetID(), ped->GetV0Norm(), time); + + // remove the pedestrian and abort + for(int p=0; p<subroom->GetNumberOfPedestrians(); p++) { + if (subroom->GetPedestrian(p)->GetID()==ped->GetID()) { + subroom->DeletePedestrian(p); + break; + } + } + + building->DeletePedFromSim(ped); + Log->Write("\tCRITICAL: one ped was removed due to high velocity"); + + // continue; + exit(EXIT_FAILURE); + } + + Point F_rep; + vector<Pedestrian*> neighbours; + building->GetGrid()->GetNeighbourhood(ped,neighbours); + + int nSize=neighbours.size(); + for (int i = 0; i < nSize; i++) { + Pedestrian* ped1 = neighbours[i]; + //if they are in the same subroom + if (ped->GetUniqueRoomID() == ped1->GetUniqueRoomID()) { + F_rep = F_rep + ForceRepPed(ped, ped1); + } else { + // or in neighbour subrooms + SubRoom* sb2=building->GetRoom(ped1->GetRoomID())->GetSubRoom(ped1->GetSubRoomID()); + if(subroom->IsDirectlyConnectedWith(sb2)) { + F_rep = F_rep + ForceRepPed(ped, ped1); + } + } + }//for peds + + //repulsive forces to the walls and transitions that are not my target + Point repwall = ForceRepRoom(allPeds[p], subroom); + Point fd = ForceDriv(ped, room); + // Point acc = (ForceDriv(ped, room) + F_rep + repwall) / ped->GetMass(); + Point acc = (fd + F_rep + repwall) / ped->GetMass(); + result_acc.push_back(acc); + } + + //#pragma omp barrier + // update + for (int p = start; p <= end; ++p) { + Pedestrian* ped = allPeds[p]; + Point v_neu = ped->GetV() + result_acc[p - start] * h; + Point pos_neu = ped->GetPos() + v_neu * h; + + Room* room = building->GetRoom(ped->GetRoomID()); + SubRoom* subroom = room->GetSubRoom(ped->GetSubRoomID()); + if(subroom->GetType()=="cellular") continue; + + //Jam is based on the current velocity + if (v_neu.Norm() >= J_EPS_V) { + ped->ResetTimeInJam(); + } else { + ped->UpdateTimeInJam(); + } + + ped->SetPos(pos_neu); + ped->SetV(v_neu); + ped->SetPhiPed(); + } + + }//end parallel + + //update the CA Model + //UpdateCellularModel(building); } // void GCFMModel::UpdateCellularModel(Building* building) const { @@ -573,461 +594,472 @@ void GCFMModel::CalculateForceLC(double time, double tip1, Building* building) c ************************************************************/ -Point GompertzModel::ForceDriv(Pedestrian* ped, Room* room) const { - const Point& target = _direction->GetTarget(room, ped); - Point F_driv; - const Point& pos = ped->GetPos(); - double dist = ped->GetExitLine()->DistTo(pos); - - - if (dist > J_EPS_GOAL) { - const Point& v0 = ped->GetV0(target); - //printf("MC v0= [%.2f %.2f]\n", v0.GetX(), v0.GetY()); - //fprintf(stderr, "%.2f %.2f %.2f %.2f %f %f\n", v0.GetX(), v0.GetY(), pos.GetX(), pos.GetY(), target.GetX(), target.GetY()); - F_driv = ((v0 * ped->GetV0Norm() - ped->GetV()) * ped->GetMass()) / ped->GetTau(); - } else { - const Point& v0 = ped->GetV0(); - //fprintf(stderr, "%.2f %.2f %.2f %.2f %f %f\n", v0.GetX(), v0.GetY(), pos.GetX(), pos.GetY(), target.GetX(), target.GetY()); - F_driv = ((v0 * ped->GetV0Norm() - ped->GetV()) * ped->GetMass()) / ped->GetTau(); - } - return F_driv; +Point GompertzModel::ForceDriv(Pedestrian* ped, Room* room) const +{ + const Point& target = _direction->GetTarget(room, ped); + Point F_driv; + const Point& pos = ped->GetPos(); + double dist = ped->GetExitLine()->DistTo(pos); + + + if (dist > J_EPS_GOAL) { + const Point& v0 = ped->GetV0(target); + //printf("MC v0= [%.2f %.2f]\n", v0.GetX(), v0.GetY()); + //fprintf(stderr, "%.2f %.2f %.2f %.2f %f %f\n", v0.GetX(), v0.GetY(), pos.GetX(), pos.GetY(), target.GetX(), target.GetY()); + F_driv = ((v0 * ped->GetV0Norm() - ped->GetV()) * ped->GetMass()) / ped->GetTau(); + } else { + const Point& v0 = ped->GetV0(); + //fprintf(stderr, "%.2f %.2f %.2f %.2f %f %f\n", v0.GetX(), v0.GetY(), pos.GetX(), pos.GetY(), target.GetX(), target.GetY()); + F_driv = ((v0 * ped->GetV0Norm() - ped->GetV()) * ped->GetMass()) / ped->GetTau(); + } + return F_driv; } -Point GompertzModel::ForceRepPed(Pedestrian* ped1, Pedestrian* ped2) const { - Point F_rep = Point(0.0, 0.0);; - // x- and y-coordinate of the distance between p1 and p2 - Point distp12 = ped2->GetPos() - ped1->GetPos(); - //const Point& vp1 = ped1->GetV(); // v Ped1 - //const Point& vp2 = ped2->GetV(); // v Ped2 - Point ep12; // x- and y-coordinate of the normalized vector between p1 and p2 - //double K_ij; - double B_ij, f; - const JEllipse& E1 = ped1->GetEllipse(); - const JEllipse& E2 = ped2->GetEllipse(); - Point AP1inE1 = E1.GetCenter(); - Point AP2inE2 = E2.GetCenter(); - // ActionPoint von E1 in Koordinaten von E2 (transformieren) - Point AP1inE2 = AP1inE1.CoordTransToEllipse(E2.GetCenter(), E2.GetCosPhi(), E2.GetSinPhi()); - // ActionPoint von E2 in Koordinaten von E1 (transformieren) - Point AP2inE1 = AP2inE2.CoordTransToEllipse(E1.GetCenter(), E1.GetCosPhi(), E1.GetSinPhi()); - double r1 = (AP1inE1 - E1.PointOnEllipse(AP2inE1)).Norm(); - double r2 = (AP2inE2 - E2.PointOnEllipse(AP1inE2)).Norm(); - double Distance = distp12.Norm(); - - // if(ped1->GetID() ==logped) - // { - // printf("ped1=%d ped2=%d Distance=%f\n",ped1->GetID(), ped2->GetID(), Distance); - // } - if (Distance >= J_EPS) { - ep12 = distp12.Normalized(); - } - else { - //printf("ERROR: \tin GompertzModel::forcePedPed() ep12 can not be calculated!!!\n"); - Log->Write("ERROR: \tin GompertzModel::forcePedPed() ep12 can not be calculated!!!\n"); - Log->Write("\t\t Pedestrians are too near to each other."); - Log->Write("\t\t Get your model right. Going to exit."); - return F_rep; // should never happen - exit(0); - } -//------------------------- check if others are behind using v0 instead of v - double tmp = ped1->GetV0().ScalarP(ep12); // < v^0_i , e_ij > - - double ped2IsBehind = exp(-exp(-5*tmp)); //step function: continuous version - if (ped2IsBehind < J_EPS){ - - // if(ped1->GetID() ==logped) - // printf("isBehind=%f\n", ped2IsBehind); - - return F_rep; // ignore ped2 - } +Point GompertzModel::ForceRepPed(Pedestrian* ped1, Pedestrian* ped2) const +{ + Point F_rep = Point(0.0, 0.0);; + // x- and y-coordinate of the distance between p1 and p2 + Point distp12 = ped2->GetPos() - ped1->GetPos(); + //const Point& vp1 = ped1->GetV(); // v Ped1 + //const Point& vp2 = ped2->GetV(); // v Ped2 + Point ep12; // x- and y-coordinate of the normalized vector between p1 and p2 + //double K_ij; + double B_ij, f; + const JEllipse& E1 = ped1->GetEllipse(); + const JEllipse& E2 = ped2->GetEllipse(); + Point AP1inE1 = E1.GetCenter(); + Point AP2inE2 = E2.GetCenter(); + // ActionPoint von E1 in Koordinaten von E2 (transformieren) + Point AP1inE2 = AP1inE1.CoordTransToEllipse(E2.GetCenter(), E2.GetCosPhi(), E2.GetSinPhi()); + // ActionPoint von E2 in Koordinaten von E1 (transformieren) + Point AP2inE1 = AP2inE2.CoordTransToEllipse(E1.GetCenter(), E1.GetCosPhi(), E1.GetSinPhi()); + double r1 = (AP1inE1 - E1.PointOnEllipse(AP2inE1)).Norm(); + double r2 = (AP2inE2 - E2.PointOnEllipse(AP1inE2)).Norm(); + double Distance = distp12.Norm(); + + // if(ped1->GetID() ==logped) + // { + // printf("ped1=%d ped2=%d Distance=%f\n",ped1->GetID(), ped2->GetID(), Distance); + // } + if (Distance >= J_EPS) { + ep12 = distp12.Normalized(); + } else { + //printf("ERROR: \tin GompertzModel::forcePedPed() ep12 can not be calculated!!!\n"); + Log->Write("ERROR: \tin GompertzModel::forcePedPed() ep12 can not be calculated!!!\n"); + Log->Write("\t\t Pedestrians are too near to each other."); + Log->Write("\t\t Get your model right. Going to exit."); + return F_rep; // should never happen + exit(0); + } +//------------------------- check if others are behind using v0 instead of v + double tmp = ped1->GetV0().ScalarP(ep12); // < v^0_i , e_ij > + + double ped2IsBehind = exp(-exp(-5*tmp)); //step function: continuous version + if (ped2IsBehind < J_EPS) { + + // if(ped1->GetID() ==logped) + // printf("isBehind=%f\n", ped2IsBehind); + + return F_rep; // ignore ped2 + } //------------------------------------------------------------------------------ - // calculate B_ij - B_ij = 1.0 - Distance/(r1+r2); //TODO: Simplification to avoid accelerating predecessors - //B_ij = 1.0 - Distance/(r1 + r2); - //Gompertz-function parameter. - //TODO: Check later if other values are more appropriate - double b = 0.25, c = 3.0; //repped - - B_ij = exp(-b*exp(-c*B_ij)); - //TODO: check if we need K_ij in the f - //f = -ped1->GetMass() * _nuPed * ped1->GetV0Norm() * K_ij * B_ij; - f = -ped1->GetMass() * _nuPed * ped1->GetV0Norm() * B_ij; - F_rep = ep12 * f; - - // if(ped1->GetID() == logped) - // { - // printf("return ----> p1=%d p2=%d Frepx=%f, Frepy=%f\n", ped1->GetID(), - // ped2->GetID(), F_rep.GetX(), F_rep.GetY()); - // printf("ped1= [%f, %f], ped2=[%f %f]\n", ped1->GetPos().GetX(), ped1->GetPos().GetY(), ped2->GetPos().GetX(), ped2->GetPos().GetY()); - // } - - //check isNan - if (F_rep.GetX() != F_rep.GetX() || F_rep.GetY() != F_rep.GetY()) { - char tmp[CLENGTH]; - sprintf(tmp, "\nNAN return ----> p1=%d p2=%d Frepx=%f, Frepy=%f\n", ped1->GetID(), - ped2->GetID(), F_rep.GetX(), F_rep.GetY()); - Log->Write(tmp); - Log->Write("ERROR:\t fix this as soon as possible"); - return Point(0,0); // FIXME: should never happen - exit(0); - } - return F_rep; + // calculate B_ij + B_ij = 1.0 - Distance/(r1+r2); //TODO: Simplification to avoid accelerating predecessors + //B_ij = 1.0 - Distance/(r1 + r2); + //Gompertz-function parameter. + //TODO: Check later if other values are more appropriate + double b = 0.25, c = 3.0; //repped + + B_ij = exp(-b*exp(-c*B_ij)); + //TODO: check if we need K_ij in the f + //f = -ped1->GetMass() * _nuPed * ped1->GetV0Norm() * K_ij * B_ij; + f = -ped1->GetMass() * _nuPed * ped1->GetV0Norm() * B_ij; + F_rep = ep12 * f; + + // if(ped1->GetID() == logped) + // { + // printf("return ----> p1=%d p2=%d Frepx=%f, Frepy=%f\n", ped1->GetID(), + // ped2->GetID(), F_rep.GetX(), F_rep.GetY()); + // printf("ped1= [%f, %f], ped2=[%f %f]\n", ped1->GetPos().GetX(), ped1->GetPos().GetY(), ped2->GetPos().GetX(), ped2->GetPos().GetY()); + // } + +//check isNan + if (F_rep.GetX() != F_rep.GetX() || F_rep.GetY() != F_rep.GetY()) { + char tmp[CLENGTH]; + sprintf(tmp, "\nNAN return ----> p1=%d p2=%d Frepx=%f, Frepy=%f\n", ped1->GetID(), + ped2->GetID(), F_rep.GetX(), F_rep.GetY()); + Log->Write(tmp); + Log->Write("ERROR:\t fix this as soon as possible"); + return Point(0,0); // FIXME: should never happen + exit(0); + } + return F_rep; }//END Gompertz:ForceRepPed() -Point GompertzModel::ForceRepRoom(Pedestrian* ped, SubRoom* subroom) const{ - Point f = Point(0., 0.); - //first the walls - const vector<Wall>& walls = subroom->GetAllWalls(); - for (int i = 0; i < subroom->GetNumberOfWalls(); i++) { - f = f + ForceRepWall(ped, walls[i]); - } - - //then the obstacles - const vector<Obstacle*>& obstacles = subroom->GetAllObstacles(); - for(unsigned int obs=0;obs<obstacles.size();++obs){ - const vector<Wall>& walls = obstacles[obs]->GetAllWalls(); - for (unsigned int i = 0; i < walls.size(); i++) { - f = f + ForceRepWall(ped, walls[i]); - } - } - // and finally the closed doors - const vector<Transition*>& transitions = subroom->GetAllTransitions(); - for (unsigned int i = 0; i < transitions.size(); i++) { - Transition* goal=transitions[i]; - if( goal->IsOpen() == false ) { - f = f + ForceRepWall(ped,*((Wall*)goal)); - } - } - - return f; +Point GompertzModel::ForceRepRoom(Pedestrian* ped, SubRoom* subroom) const +{ + Point f = Point(0., 0.); + //first the walls + const vector<Wall>& walls = subroom->GetAllWalls(); + for (int i = 0; i < subroom->GetNumberOfWalls(); i++) { + f = f + ForceRepWall(ped, walls[i]); + } + + //then the obstacles + const vector<Obstacle*>& obstacles = subroom->GetAllObstacles(); + for(unsigned int obs=0; obs<obstacles.size(); ++obs) { + const vector<Wall>& walls = obstacles[obs]->GetAllWalls(); + for (unsigned int i = 0; i < walls.size(); i++) { + f = f + ForceRepWall(ped, walls[i]); + } + } + // and finally the closed doors + const vector<Transition*>& transitions = subroom->GetAllTransitions(); + for (unsigned int i = 0; i < transitions.size(); i++) { + Transition* goal=transitions[i]; + if( goal->IsOpen() == false ) { + f = f + ForceRepWall(ped,*((Wall*)goal)); + } + } + + return f; } -Point GompertzModel::ForceRepWall(Pedestrian* ped, const Wall& w) const{ - Point F_wrep = Point(0.0, 0.0); - // printf("in GompertzWall\n"); - // getc(stdin); - // if direction of pedestrians does not intersect walls --> ignore - - Point pt = w.ShortestPoint(ped->GetPos()); - double wlen = w.LengthSquare(); - if (wlen <= 0.03) { // ignore walls smaller than 0.15m (15cm) - // if(ped->GetID() == 33) - // printf ("Wall beeing ignored [%f %f]<-->[%f %f]\n", w.GetPoint1().GetX(), w.GetPoint1().GetY(), w.GetPoint2().GetX(), w.GetPoint2().GetY()); - return F_wrep; - } - Point dist = pt - ped->GetPos(); // x- and y-coordinate of the distance between ped and p - double Distance = dist.Norm(); // distance between the centre of ped and point p - //double vn = w.NormalComp(ped->GetV()); //normal component of the velocity on the wall - Point e_iw; // x- and y-coordinate of the normalized vector between ped and pt - //double K_iw; - double Radius, B_iw; - double tmp; - double f; - Point r; - Point pinE; // vorher x1, y1 - const JEllipse& E = ped->GetEllipse(); - const Point& v = ped->GetV(); - - if (Distance < J_EPS){ - Log->Write("WARNING:\t Gompertz: forceRepWall() ped %d is too near to the wall. Return default values",ped->GetID()); - return Point(0, 0); //quick and dirty. Should react to the warning and fix the model - } - e_iw = dist / Distance; - // tmp = v.ScalarP(e_iw); // < v_i , e_iw >; - // bla = (tmp + fabs(tmp)); - // if (bla < J_EPS) // Wall is behind the direction of motion - // return F; - +Point GompertzModel::ForceRepWall(Pedestrian* ped, const Wall& w) const +{ + Point F_wrep = Point(0.0, 0.0); + // printf("in GompertzWall\n"); + // getc(stdin); + // if direction of pedestrians does not intersect walls --> ignore + + Point pt = w.ShortestPoint(ped->GetPos()); + double wlen = w.LengthSquare(); + if (wlen <= 0.03) { // ignore walls smaller than 0.15m (15cm) + // if(ped->GetID() == 33) + // printf ("Wall beeing ignored [%f %f]<-->[%f %f]\n", w.GetPoint1().GetX(), w.GetPoint1().GetY(), w.GetPoint2().GetX(), w.GetPoint2().GetY()); + return F_wrep; + } + Point dist = pt - ped->GetPos(); // x- and y-coordinate of the distance between ped and p + double Distance = dist.Norm(); // distance between the centre of ped and point p + //double vn = w.NormalComp(ped->GetV()); //normal component of the velocity on the wall + Point e_iw; // x- and y-coordinate of the normalized vector between ped and pt + //double K_iw; + double Radius, B_iw; + double tmp; + double f; + Point r; + Point pinE; // vorher x1, y1 + const JEllipse& E = ped->GetEllipse(); + const Point& v = ped->GetV(); + + if (Distance < J_EPS) { + Log->Write("WARNING:\t Gompertz: forceRepWall() ped %d is too near to the wall. Return default values",ped->GetID()); + return Point(0, 0); //quick and dirty. Should react to the warning and fix the model + } + e_iw = dist / Distance; + // tmp = v.ScalarP(e_iw); // < v_i , e_iw >; + // bla = (tmp + fabs(tmp)); + // if (bla < J_EPS) // Wall is behind the direction of motion + // return F; + //------------------------- check if others are behind using v0 instead of v - tmp = ped->GetV0().ScalarP(e_iw); // < v^0_i , e_iw > - double tmpv = v.ScalarP(e_iw); - double wallIsBehind = exp(-exp(-5*tmp)); //step function: continuous version - double wallIsBehindv = exp(-exp(-5*tmpv)); //step function: continuous version - // if(ped->GetID() == 40) - // { - // printf ("Wall [%f %f]<-->[%f %f]\n", w.GetPoint1().GetX(), w.GetPoint1().GetY(), w.GetPoint2().GetX(), w.GetPoint2().GetY()); - // printf("v=[%f, %f] v0=[%f, %f] eiw=[%f, %f], wlen=%f\n",v.GetX(), v.GetY(), ped->GetV0().GetX(),ped->GetV0().GetY(), e_iw.GetX(), e_iw.GetY(), wlen); - // printf("tmp=%f, tmpv=%f\n",tmp, tmpv); - // printf("wall2IsBehind=%f, wallIsBehindv=%f\n", wallIsBehind, wallIsBehindv); - // } - - - - if ( wallIsBehindv < J_EPS && wallIsBehind < J_EPS) { // Wall is behind the direction of motion - return F_wrep; - } + tmp = ped->GetV0().ScalarP(e_iw); // < v^0_i , e_iw > + double tmpv = v.ScalarP(e_iw); + double wallIsBehind = exp(-exp(-5*tmp)); //step function: continuous version + double wallIsBehindv = exp(-exp(-5*tmpv)); //step function: continuous version + // if(ped->GetID() == 40) + // { + // printf ("Wall [%f %f]<-->[%f %f]\n", w.GetPoint1().GetX(), w.GetPoint1().GetY(), w.GetPoint2().GetX(), w.GetPoint2().GetY()); + // printf("v=[%f, %f] v0=[%f, %f] eiw=[%f, %f], wlen=%f\n",v.GetX(), v.GetY(), ped->GetV0().GetX(),ped->GetV0().GetY(), e_iw.GetX(), e_iw.GetY(), wlen); + // printf("tmp=%f, tmpv=%f\n",tmp, tmpv); + // printf("wall2IsBehind=%f, wallIsBehindv=%f\n", wallIsBehind, wallIsBehindv); + // } + + + + if ( wallIsBehindv < J_EPS && wallIsBehind < J_EPS) { // Wall is behind the direction of motion + return F_wrep; + } //------------------------------------------------------------------------ // if (fabs(v.GetX()) < J_EPS_V && fabs(v.GetY()) < J_EPS_V) // v==0) - // return F; - - // K_iw = 0.5 * bla / v.Norm(); // K_iw - - // pt in coordinate system of Ellipse - pinE = pt.CoordTransToEllipse(E.GetCenter(), E.GetCosPhi(), E.GetSinPhi()); - // Punkt auf der Ellipse - r = E.PointOnEllipse(pinE); - Radius = (r - E.GetCenter()).Norm(); - - //------------------------- - - const Point& pos = ped->GetPos(); - double distGoal = ped->GetExitLine()->DistTo(pos); - if(distGoal < J_EPS_GOAL) - return F_wrep; - - Line direction = Line(ped->GetPos(), ped->GetPos() + v*100); - if(Distance>Radius && direction.IntersectionWith(w) == false ) - { - return F_wrep; - } - + // return F; + + // K_iw = 0.5 * bla / v.Norm(); // K_iw + + // pt in coordinate system of Ellipse + pinE = pt.CoordTransToEllipse(E.GetCenter(), E.GetCosPhi(), E.GetSinPhi()); + // Punkt auf der Ellipse + r = E.PointOnEllipse(pinE); + Radius = (r - E.GetCenter()).Norm(); + + //------------------------- + + const Point& pos = ped->GetPos(); + double distGoal = ped->GetExitLine()->DistTo(pos); + if(distGoal < J_EPS_GOAL) + return F_wrep; + + Line direction = Line(ped->GetPos(), ped->GetPos() + v*100); + if(Distance>Radius && direction.IntersectionWith(w) == false ) { + return F_wrep; + } + //------------------------- - //TODO: Check later if other values are more appropriate - double b = 0.7, c = 3.0; - B_iw = 1.0 - Distance/(Radius); - B_iw = exp(-b*exp(-c*B_iw)); - //f = -ped->GetMass() * _nuWall * ped->GetV0Norm() * K_iw * B_iw; - f = -ped->GetMass() * _nuWall * B_iw * ped->GetV0Norm(); + //TODO: Check later if other values are more appropriate + double b = 0.7, c = 3.0; + B_iw = 1.0 - Distance/(Radius); + B_iw = exp(-b*exp(-c*B_iw)); + //f = -ped->GetMass() * _nuWall * ped->GetV0Norm() * K_iw * B_iw; + f = -ped->GetMass() * _nuWall * B_iw * ped->GetV0Norm(); - F_wrep = e_iw * f; + F_wrep = e_iw * f; // if(1)// && F_wrep.Norm()>J_EPS && w.GetPoint1().GetX()==w.GetPoint2().GetX() ) - // { + // { // printf("\n---- %d Radius=%f, dist=%f\n",ped->GetID(), Radius, Distance); // printf ("Wall [%f %f]<-->[%f %f] Force=[%f ,%f]\n", w.GetPoint1().GetX(), w.GetPoint1().GetY(), w.GetPoint2().GetX(), w.GetPoint2().GetY(), F_wrep.GetX(), F_wrep.GetY()); // printf("X= %f, Y=%f\n",ped->GetPos().GetX(), ped->GetPos().GetY()); // } - return F_wrep; + return F_wrep; } -void GompertzModel::CalculateForceLC(double time, double tip1, Building* building) const { - double delta = 0.5; - double h = tip1 - time; - // collect all pedestrians in the simulation. - const vector< Pedestrian* >& allPeds = building->GetAllPedestrians(); +void GompertzModel::CalculateForceLC(double time, double tip1, Building* building) const +{ + double delta = 0.5; + double h = tip1 - time; + // collect all pedestrians in the simulation. + const vector< Pedestrian* >& allPeds = building->GetAllPedestrians(); - unsigned int nSize = allPeds.size(); + unsigned int nSize = allPeds.size(); - int nThreads = omp_get_max_threads(); + int nThreads = omp_get_max_threads(); - // check if worth sharing the work - if (nSize < 20) nThreads = 1; - int partSize = nSize / nThreads; + // check if worth sharing the work + if (nSize < 20) nThreads = 1; + int partSize = nSize / nThreads; -#pragma omp parallel default(shared) num_threads(nThreads) - { - vector< Point > result_acc = vector<Point > (); - result_acc.reserve(2200); //FIXME What is 2200? + #pragma omp parallel default(shared) num_threads(nThreads) + { + vector< Point > result_acc = vector<Point > (); + result_acc.reserve(2200); //FIXME What is 2200? - const int threadID = omp_get_thread_num(); + const int threadID = omp_get_thread_num(); - int start = threadID*partSize; - int end = (threadID + 1) * partSize - 1; - if ((threadID == nThreads - 1)) end = nSize - 1; + int start = threadID*partSize; + int end = (threadID + 1) * partSize - 1; + if ((threadID == nThreads - 1)) end = nSize - 1; - for (int p = start; p <= end; ++p) { + for (int p = start; p <= end; ++p) { - Pedestrian* ped = allPeds[p]; - Room* room = building->GetRoom(ped->GetRoomID()); - SubRoom* subroom = room->GetSubRoom(ped->GetSubRoomID()); + Pedestrian* ped = allPeds[p]; + Room* room = building->GetRoom(ped->GetRoomID()); + SubRoom* subroom = room->GetSubRoom(ped->GetSubRoomID()); - double normVi = ped->GetV().ScalarP(ped->GetV()); //squared - double HighVel = (ped->GetV0Norm() + delta) * (ped->GetV0Norm() + delta); //(v0+delta)^2 - if (0 && normVi > HighVel && ped->GetV0Norm() > 0) { - fprintf(stderr, "GompertzModel::calculateForce_LC() WARNING: actual velocity (%f) of iped %d " - "is bigger than desired velocity (%f) at time: %fs\n", - sqrt(normVi), ped->GetID(), ped->GetV0Norm(), time); + double normVi = ped->GetV().ScalarP(ped->GetV()); //squared + double HighVel = (ped->GetV0Norm() + delta) * (ped->GetV0Norm() + delta); //(v0+delta)^2 + if (0 && normVi > HighVel && ped->GetV0Norm() > 0) { + fprintf(stderr, "GompertzModel::calculateForce_LC() WARNING: actual velocity (%f) of iped %d " + "is bigger than desired velocity (%f) at time: %fs\n", + sqrt(normVi), ped->GetID(), ped->GetV0Norm(), time); - // remove the pedestrian and abort - for(int p=0;p<subroom->GetNumberOfPedestrians();p++){ - if (subroom->GetPedestrian(p)->GetID() == ped->GetID()){ - subroom->DeletePedestrian(p); - break; + // remove the pedestrian and abort + for(int p=0; p<subroom->GetNumberOfPedestrians(); p++) { + if (subroom->GetPedestrian(p)->GetID() == ped->GetID()) { + subroom->DeletePedestrian(p); + break; + } } - } - - printf("\tCCRITICAL: ped [%d] was removed due to high velocity\n",ped->GetID()); - Log->Write("\tCRITICAL: ped [%d] was removed due to high velocity",ped->GetID()); - - building->DeletePedestrian(ped); - //continue; //FIXME tolerate first - exit(EXIT_FAILURE); - } - - Point repPed = Point(0,0); - vector<Pedestrian*> neighbours; - building->GetGrid()->GetNeighbourhood(ped,neighbours); - - int nSize = neighbours.size(); - // double B_ij=0; - // int count_Bij=0; - - for (int i = 0; i < nSize; i++) { - Pedestrian* ped1 = neighbours[i]; - //-------------- TESTING --------- - // Point distp12 = ped1->GetPos() - ped->GetPos(); - // double Distance = distp12.Norm(); - // double tmp; - // tmp = 1.0 - Distance/(0.35 + 0.35); - // B_ij += exp(-1*exp(-1*tmp)); - // if (B_ij > J_EPS) - // count_Bij += 1; - // if (ped->GetID()==logped) - // printf("Bij=%f, dist=%f\n", B_ij, Distance); - //-------------------------------- - //if they are in the same subroom - if (ped->GetUniqueRoomID() == ped1->GetUniqueRoomID()) { - repPed = repPed + ForceRepPed(ped, ped1); - } - else { - // or in neighbour subrooms - SubRoom* sb2=building->GetRoom(ped1->GetRoomID())->GetSubRoom(ped1->GetSubRoomID()); - if(subroom->IsDirectlyConnectedWith(sb2)){ - repPed = repPed + ForceRepPed(ped, ped1); + + printf("\tCCRITICAL: ped [%d] was removed due to high velocity\n",ped->GetID()); + Log->Write("\tCRITICAL: ped [%d] was removed due to high velocity",ped->GetID()); + + building->DeletePedestrian(ped); + //continue; //FIXME tolerate first + exit(EXIT_FAILURE); + } + + Point repPed = Point(0,0); + vector<Pedestrian*> neighbours; + building->GetGrid()->GetNeighbourhood(ped,neighbours); + + int nSize = neighbours.size(); + // double B_ij=0; + // int count_Bij=0; + + for (int i = 0; i < nSize; i++) { + Pedestrian* ped1 = neighbours[i]; + //-------------- TESTING --------- + // Point distp12 = ped1->GetPos() - ped->GetPos(); + // double Distance = distp12.Norm(); + // double tmp; + // tmp = 1.0 - Distance/(0.35 + 0.35); + // B_ij += exp(-1*exp(-1*tmp)); + // if (B_ij > J_EPS) + // count_Bij += 1; + // if (ped->GetID()==logped) + // printf("Bij=%f, dist=%f\n", B_ij, Distance); + //-------------------------------- + //if they are in the same subroom + if (ped->GetUniqueRoomID() == ped1->GetUniqueRoomID()) { + repPed = repPed + ForceRepPed(ped, ped1); + } else { + // or in neighbour subrooms + SubRoom* sb2=building->GetRoom(ped1->GetRoomID())->GetSubRoom(ped1->GetSubRoomID()); + if(subroom->IsDirectlyConnectedWith(sb2)) { + repPed = repPed + ForceRepPed(ped, ped1); + } } - } - } - //repulsive forces to walls and closed transitions that are not my target - Point repWall = ForceRepRoom(allPeds[p], subroom); - Point fd = ForceDriv(ped, room); - // if(count_Bij) - // B_ij /=count_Bij; - // else - // B_ij = 0; - // double correction = ped->GetV0Norm()*(-B_ij)/ped->GetTau(); - - - //fprintf(stderr, "%f\n", correction); - // if (ped->GetID()==logped){ - // printf("Bij=%f, count=%d\n", B_ij, count_Bij); - // printf(">>MC Gompertz fd=[%.2f, %.2f] F_rep=[%.2f, %.2f], repWall=[%.2f, %.2f] cor=%f\n", fd.GetX(), fd.GetY(), repPed.GetX(), repPed.GetY(), repWall.GetX(), repWall.GetY(), correction ); - // } - - // make pedestrians want to walk slower in jam - //fd = fd + Point(correction, correction); - - Point acc = (fd + repPed + repWall) / ped->GetMass(); - // if (1){ - // printf("<<%d GOMPERTZ fd=[%.2f, %.2f] F_rep=[%.2f, %.2f], repWall=[%.2f, %.2f], acc=[%.2f, %.2f]\n",ped->GetID(), fd.GetX(), fd.GetY(), repPed.GetX(), repPed.GetY(), repWall.GetX(), repWall.GetY(), acc.GetX(), acc.GetY() ); - // } + } + //repulsive forces to walls and closed transitions that are not my target + Point repWall = ForceRepRoom(allPeds[p], subroom); + Point fd = ForceDriv(ped, room); + // if(count_Bij) + // B_ij /=count_Bij; + // else + // B_ij = 0; + // double correction = ped->GetV0Norm()*(-B_ij)/ped->GetTau(); + + + //fprintf(stderr, "%f\n", correction); + // if (ped->GetID()==logped){ + // printf("Bij=%f, count=%d\n", B_ij, count_Bij); + // printf(">>MC Gompertz fd=[%.2f, %.2f] F_rep=[%.2f, %.2f], repWall=[%.2f, %.2f] cor=%f\n", fd.GetX(), fd.GetY(), repPed.GetX(), repPed.GetY(), repWall.GetX(), repWall.GetY(), correction ); + // } + + // make pedestrians want to walk slower in jam + //fd = fd + Point(correction, correction); + + Point acc = (fd + repPed + repWall) / ped->GetMass(); + // if (1){ + // printf("<<%d GOMPERTZ fd=[%.2f, %.2f] F_rep=[%.2f, %.2f], repWall=[%.2f, %.2f], acc=[%.2f, %.2f]\n",ped->GetID(), fd.GetX(), fd.GetY(), repPed.GetX(), repPed.GetY(), repWall.GetX(), repWall.GetY(), acc.GetX(), acc.GetY() ); + // } //--------------------------------- limiting high accelerations to v0/tau *coef - // double nacc = acc.Norm(); - //double maxf = ped->GetV0Norm()/ped->GetTau(); - // if (0 && nacc > maxf){ - // Point tacc = acc/nacc; - // if (ped->GetID()==logped){ - // printf("acc BEVOORE acc=[%.2f, %.2f] maxf->%f\n, nacc=%f\n\n", acc.GetX(), acc.GetY(), maxf, nacc); - // } - // acc = tacc * maxf* 0.2; - // if (ped->GetID()==logped){ - // printf("acc CHANGED acc=[%.2f, %.2f] maxf->%f\n, nacc=%f\n\n", acc.GetX(), acc.GetY(), maxf, nacc); - // } - // } + // double nacc = acc.Norm(); + //double maxf = ped->GetV0Norm()/ped->GetTau(); + // if (0 && nacc > maxf){ + // Point tacc = acc/nacc; + // if (ped->GetID()==logped){ + // printf("acc BEVOORE acc=[%.2f, %.2f] maxf->%f\n, nacc=%f\n\n", acc.GetX(), acc.GetY(), maxf, nacc); + // } + // acc = tacc * maxf* 0.2; + // if (ped->GetID()==logped){ + // printf("acc CHANGED acc=[%.2f, %.2f] maxf->%f\n, nacc=%f\n\n", acc.GetX(), acc.GetY(), maxf, nacc); + // } + // } //------------------------------------------------------------------------------------------ - result_acc.push_back(acc); - } - - //#pragma omp barrier - // update - for (int p = start; p <= end; ++p) { - Pedestrian* ped = allPeds[p]; - - Point vToAdd = result_acc[p - start] * h; - //----------------- update new pos and new vel ----------------- - Point v_neu = ped->GetV() + vToAdd; - Point pos_neu = ped->GetPos() + v_neu * h; - //--------------------------------------------------------------- - //Room* room = building->GetRoom(ped->GetRoomID()); - //SubRoom* subroom = room->GetSubRoom(ped->GetSubRoomID()); - //if(subroom->GetType()=="cellular") continue; - - - Point e0 = ped->GetV0(); - double isBackwards; - //isBackwards = ped->GetV().GetX()*e0.GetX() + ped->GetV().GetX()*e0.GetY(); - isBackwards = v_neu.GetX()*e0.GetX() + v_neu.GetY()*e0.GetY(); - - - - // if (ped->GetID()==logped){ - // printf("<<MC GOMPERTZ v=[%.2f, %.2f] v0=[%.2f, %.2f], isBack=[%.8f]\n", ped->GetV().GetX(), ped->GetV().GetY(), e0.GetX(), e0.GetY(), isBackwards ); - // } - - if (ped->GetV().Norm()>J_EPS_V) - { - isBackwards = isBackwards/(v_neu.Norm() * e0.Norm()); //normalize - if(isBackwards <= J_EPS_V) // Pedestrian is moving in the wrong direction - { - // if (ped->GetID()==logped){ - // printf("\t\tBREAK\n"); - // } + result_acc.push_back(acc); + } + + //#pragma omp barrier + // update + for (int p = start; p <= end; ++p) { + Pedestrian* ped = allPeds[p]; + + Point vToAdd = result_acc[p - start] * h; + //----------------- update new pos and new vel ----------------- + Point v_neu = ped->GetV() + vToAdd; + Point pos_neu = ped->GetPos() + v_neu * h; + //--------------------------------------------------------------- + //Room* room = building->GetRoom(ped->GetRoomID()); + //SubRoom* subroom = room->GetSubRoom(ped->GetSubRoomID()); + //if(subroom->GetType()=="cellular") continue; + + + Point e0 = ped->GetV0(); + double isBackwards; + //isBackwards = ped->GetV().GetX()*e0.GetX() + ped->GetV().GetX()*e0.GetY(); + isBackwards = v_neu.GetX()*e0.GetX() + v_neu.GetY()*e0.GetY(); + + + + // if (ped->GetID()==logped){ + // printf("<<MC GOMPERTZ v=[%.2f, %.2f] v0=[%.2f, %.2f], isBack=[%.8f]\n", ped->GetV().GetX(), ped->GetV().GetY(), e0.GetX(), e0.GetY(), isBackwards ); + // } + + if (ped->GetV().Norm()>J_EPS_V) { + isBackwards = isBackwards/(v_neu.Norm() * e0.Norm()); //normalize + if(isBackwards <= J_EPS_V) { // Pedestrian is moving in the wrong direction + // if (ped->GetID()==logped){ + // printf("\t\tBREAK\n"); + // } + v_neu = v_neu*0.01; + pos_neu = ped->GetPos() + v_neu *h ; + } + } + + if(v_neu.Norm() > ped->GetV0Norm()+0.2 ) { // Stop pedestrians v_neu = v_neu*0.01; - pos_neu = ped->GetPos() + v_neu *h ; - } - } - - if(v_neu.Norm() > ped->GetV0Norm()+0.2 ) // Stop pedestrians - { - v_neu = v_neu*0.01; - pos_neu = ped->GetPos(); - } + pos_neu = ped->GetPos(); + } //--------------------------------------- apparently this depends on the chosen model Issue 9 ----- - //Jam is based on the current velocity + //Jam is based on the current velocity // if ( v_neu.Norm() >= J_EPS_V){ // ped->ResetTimeInJam(); // }else{ // ped->UpdateTimeInJam(); // } - if ( v_neu.Norm() >= ped->GetV0Norm()*0.5){ - ped->ResetTimeInJam(); - }else{ - ped->UpdateTimeInJam(); - } + if ( v_neu.Norm() >= ped->GetV0Norm()*0.5) { + ped->ResetTimeInJam(); + } else { + ped->UpdateTimeInJam(); + } //-------------------------------------------------------------------------------------------------- - // if (ped->GetID()==logped){ - // printf("<<MC GOMPERTZ pos=[%.2f, %.2f] vv=[%.2f, %.2f]\n", ped->GetPos().GetX(), ped->GetPos().GetY(), ped->GetV().GetX(), ped->GetV().GetY()); - // printf("<<MC GOMPERTZ pos_new=[%.2f, %.2f] vv_new=[%.2f, %.2f]\n", pos_neu.GetX(), pos_neu.GetY(), v_neu.GetX(), v_neu.GetY()); - // //getc(stdin); - // } - - ped->SetPos(pos_neu); - ped->SetV(v_neu); - ped->SetPhiPed(); - } - }//end parallel -} -string GompertzModel::writeParameter() const { - string rueck; - char tmp[CLENGTH]; + // if (ped->GetID()==logped){ + // printf("<<MC GOMPERTZ pos=[%.2f, %.2f] vv=[%.2f, %.2f]\n", ped->GetPos().GetX(), ped->GetPos().GetY(), ped->GetV().GetX(), ped->GetV().GetY()); + // printf("<<MC GOMPERTZ pos_new=[%.2f, %.2f] vv_new=[%.2f, %.2f]\n", pos_neu.GetX(), pos_neu.GetY(), v_neu.GetX(), v_neu.GetY()); + // //getc(stdin); + // } - sprintf(tmp, "\t\tNu: \t\tPed: %f \tWall: %f\n", _nuPed, _nuWall); - rueck.append(tmp); - return rueck; + ped->SetPos(pos_neu); + ped->SetV(v_neu); + ped->SetPhiPed(); + } + }//end parallel +} +string GompertzModel::writeParameter() const +{ + string rueck; + char tmp[CLENGTH]; + + sprintf(tmp, "\t\tNu: \t\tPed: %f \tWall: %f\n", _nuPed, _nuWall); + rueck.append(tmp); + return rueck; +} +DirectionStrategy* GompertzModel::GetDirection() const +{ + return _direction; } -DirectionStrategy* GompertzModel::GetDirection() const { return _direction;} -double GompertzModel::GetNuPed() const {return _nuPed;} +double GompertzModel::GetNuPed() const +{ + return _nuPed; +} -double GompertzModel::GetNuWall() const {return _nuWall;} +double GompertzModel::GetNuWall() const +{ + return _nuWall; +} -GompertzModel::GompertzModel(DirectionStrategy* dir, double nuped, double nuwall) { - _direction = dir; - _nuPed = nuped; - _nuWall = nuwall; +GompertzModel::GompertzModel(DirectionStrategy* dir, double nuped, double nuwall) +{ + _direction = dir; + _nuPed = nuped; + _nuWall = nuwall; } void GompertzModel::CalculateForce(double time, vector< Point >& result_acc, Building* building, - int roomID, int subroomID) const { + int roomID, int subroomID) const +{ - printf("CalculateForce is not working: you should not use this function"); - exit(0); + printf("CalculateForce is not working: you should not use this function"); + exit(0); } GompertzModel::~GompertzModel(void) { } diff --git a/math/ForceModel.h b/math/ForceModel.h index b3bd8368fb021db9f364e149d57cee6a6a107b57..050c63adc5568037348bf1e4907828fa36cb4b0c 100644 --- a/math/ForceModel.h +++ b/math/ForceModel.h @@ -1,10 +1,10 @@ /** * @file ForceModel.h * - * @brief Implementation of classes for some force-based models + * @brief Implementation of classes for some force-based models * * @section LICENSE - * This file is part of JuPedSim. + * This file is part of JuPedSim. * * JuPedSim is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,10 +20,10 @@ * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. * * @section DESCRIPTION - * Implementation of classes for force-based models. - * Actually we've got two different models: + * Implementation of classes for force-based models. + * Actually we've got two different models: * 1. Generalized Centrifugal Force Model - * 2. Gompertz Model + * 2. Gompertz Model * * @date Tue Apr 15 19:19:04 2014 */ @@ -44,34 +44,34 @@ class DirectionStrategy; /** * @date Fri Apr 18 16:40:39 2014 - * + * * @brief The operative model. Definition of several force-based models - * for ped pedestrians dynamics - * - * + * for ped pedestrians dynamics + * + * */ class ForceModel { - public: - // Konstruktoren - ForceModel(); - virtual ~ForceModel(); +public: + // Konstruktoren + ForceModel(); + virtual ~ForceModel(); - //FIXME: remove - virtual void CalculateForce(double time, std::vector< Point >& result_acc, Building* building, int roomID, int SubRoomID) const = 0; + //FIXME: remove + virtual void CalculateForce(double time, std::vector< Point >& result_acc, Building* building, int roomID, int SubRoomID) const = 0; - /** - * Solve the differential equations and update the positions and velocities - * @param t the actual time - * @param tp the next timestep - * @param building the geometry object - */ - virtual void CalculateForceLC(double t, double tp, Building* building) const = 0; + /** + * Solve the differential equations and update the positions and velocities + * @param t the actual time + * @param tp the next timestep + * @param building the geometry object + */ + virtual void CalculateForceLC(double t, double tp, Building* building) const = 0; - /** - * @return all model parameters in a nicely formatted string - */ - virtual std::string writeParameter() const = 0; + /** + * @return all model parameters in a nicely formatted string + */ + virtual std::string writeParameter() const = 0; }; /************************************************************ @@ -79,177 +79,177 @@ class ForceModel { ************************************************************/ /** * @date Fri Apr 18 16:39:13 2014 - * + * * @brief The Generalized Centrifugal Force Model - * - * + * + * */ class GCFMModel : public ForceModel { - private: - /// define the strategy for crossing a door (used for calculating the driving force) - DirectionStrategy* _direction; - // Modellparameter - double _nuPed; /**< strength of the pedestrian repulsive force */ - double _nuWall; /**< strength of the wall repulsive force */ - double _intp_widthPed; /**< Interpolation cutoff radius (in cm) */ - double _intp_widthWall; /**< Interpolation cutoff radius (in cm) */ - double _maxfPed; - double _maxfWall; - double _distEffMaxPed; // maximal effective distance - double _distEffMaxWall; // maximal effective distance +private: + /// define the strategy for crossing a door (used for calculating the driving force) + DirectionStrategy* _direction; + // Modellparameter + double _nuPed; /**< strength of the pedestrian repulsive force */ + double _nuWall; /**< strength of the wall repulsive force */ + double _intp_widthPed; /**< Interpolation cutoff radius (in cm) */ + double _intp_widthWall; /**< Interpolation cutoff radius (in cm) */ + double _maxfPed; + double _maxfWall; + double _distEffMaxPed; // maximal effective distance + double _distEffMaxWall; // maximal effective distance - // Private Funktionen - /** - * Driving force \f$ F_i =\frac{\mathbf{v_0}-\mathbf{v_i}}{\tau}\f$ - * - * @param ped Pointer to Pedestrians - * @param room Pointer to Room - * - * @return Point - */ - Point ForceDriv(Pedestrian* ped, Room* room) const; - /** - * Repulsive force between two pedestrians ped1 and ped2 according to - * the Generalized Centrifugal Force Model (chraibi2010a) - * - * @param ped1 Pointer to Pedestrian: First pedestrian - * @param ped2 Pointer to Pedestrian: Second pedestrian - * - * @return Point - */ - Point ForceRepPed(Pedestrian* ped1, Pedestrian* ped2) const; - /** - * Repulsive force acting on pedestrian <ped> from the walls in - * <subroom>. The sum of all repulsive forces of the walls in <subroom> is calculated - * @see ForceRepWall - * @param ped Pointer to Pedestrian - * @param subroom Pointer to SubRoom - * - * @return - */ - Point ForceRepRoom(Pedestrian* ped, SubRoom* subroom) const; - Point ForceRepWall(Pedestrian* ped, const Wall& l) const; - Point ForceRepStatPoint(Pedestrian* ped, const Point& p, double l, double vn) const; - Point ForceInterpolation(double v0, double K_ij, const Point& e, double v, double d, double r, double l) const; - public: + // Private Funktionen + /** + * Driving force \f$ F_i =\frac{\mathbf{v_0}-\mathbf{v_i}}{\tau}\f$ + * + * @param ped Pointer to Pedestrians + * @param room Pointer to Room + * + * @return Point + */ + Point ForceDriv(Pedestrian* ped, Room* room) const; + /** + * Repulsive force between two pedestrians ped1 and ped2 according to + * the Generalized Centrifugal Force Model (chraibi2010a) + * + * @param ped1 Pointer to Pedestrian: First pedestrian + * @param ped2 Pointer to Pedestrian: Second pedestrian + * + * @return Point + */ + Point ForceRepPed(Pedestrian* ped1, Pedestrian* ped2) const; + /** + * Repulsive force acting on pedestrian <ped> from the walls in + * <subroom>. The sum of all repulsive forces of the walls in <subroom> is calculated + * @see ForceRepWall + * @param ped Pointer to Pedestrian + * @param subroom Pointer to SubRoom + * + * @return + */ + Point ForceRepRoom(Pedestrian* ped, SubRoom* subroom) const; + Point ForceRepWall(Pedestrian* ped, const Wall& l) const; + Point ForceRepStatPoint(Pedestrian* ped, const Point& p, double l, double vn) const; + Point ForceInterpolation(double v0, double K_ij, const Point& e, double v, double d, double r, double l) const; +public: - GCFMModel(DirectionStrategy* dir, double nuped, double nuwall, double dist_effPed, double dist_effWall, - double intp_widthped, double intp_widthwall, double maxfped, double maxfwall); - virtual ~GCFMModel(void); + GCFMModel(DirectionStrategy* dir, double nuped, double nuwall, double dist_effPed, double dist_effWall, + double intp_widthped, double intp_widthwall, double maxfped, double maxfwall); + virtual ~GCFMModel(void); - // Getter - DirectionStrategy* GetDirection() const; - double GetNuPed() const; - double GetNuWall() const; - double GetDistEffMax() const; - double GetIntpWidthPed() const; - double GetIntpWidthWall() const; - double GetMaxFPed() const; - double GetMaxFWall() const; - double GetDistEffMaxPed() const; - double GetDistEffMaxWall() const; + // Getter + DirectionStrategy* GetDirection() const; + double GetNuPed() const; + double GetNuWall() const; + double GetDistEffMax() const; + double GetIntpWidthPed() const; + double GetIntpWidthWall() const; + double GetMaxFPed() const; + double GetMaxFWall() const; + double GetDistEffMaxPed() const; + double GetDistEffMaxWall() const; - //void UpdateCellularModel(Building* building) const; + //void UpdateCellularModel(Building* building) const; - // virtuelle Funktionen - virtual void CalculateForce(double time, std::vector< Point >& result_acc, Building* building, - int roomID, int SubRoomID) const; - virtual void CalculateForceLC(double t, double tp, Building* building) const; - virtual std::string writeParameter() const; + // virtuelle Funktionen + virtual void CalculateForce(double time, std::vector< Point >& result_acc, Building* building, + int roomID, int SubRoomID) const; + virtual void CalculateForceLC(double t, double tp, Building* building) const; + virtual std::string writeParameter() const; }; /************************************************************ GOMPERTZ ForceModel ************************************************************/ -/** +/** * Class defining the Gompertz model - * - * - * @brief The Gompertz model. Not yet published. + * + * + * @brief The Gompertz model. Not yet published. */ class GompertzModel : public ForceModel { - private: - /// define the strategy for crossing a door (used for calculating the driving force) - DirectionStrategy* _direction; - - /// Modellparameter - double _nuPed; - double _nuWall; - - /** - * Driving force \f$ F_i =\frac{\mathbf{v_0}-\mathbf{v_i}}{\tau}\$ - * This is a duplicate of @see GCFMModel::ForceDriv - * @param ped Pointer to Pedestrians - * @param room Pointer to Room - * - * - * @return Point - */ - Point ForceDriv(Pedestrian* ped, Room* room) const; - /** - * Repulsive force between two pedestrians ped1 and ped2 according to - * the Gompertz model (unpublished) - * - * @param ped1 Pointer to Pedestrian: First pedestrian - * @param ped2 Pointer to Pedestrian: Second pedestrian - * - * @return Point - */ - Point ForceRepPed(Pedestrian* ped1, Pedestrian* ped2) const; - /** - * Repulsive force acting on pedestrian <ped> from the walls in - * <subroom>. The sum of all repulsive forces of the walls in <subroom> is calculated - * @see ForceRepWall - * @param ped Pointer to Pedestrian - * @param subroom Pointer to SubRoom - * - * @return Point - */ - Point ForceRepRoom(Pedestrian* ped, SubRoom* subroom) const; - /** - * Repulsive force between pedestrian <ped> and wall <l> - * - * @param ped Pointer to Pedestrian - * @param l reference to Wall - * - * @return Point - */ - Point ForceRepWall(Pedestrian* ped, const Wall& l) const; +private: + /// define the strategy for crossing a door (used for calculating the driving force) + DirectionStrategy* _direction; + + /// Modellparameter + double _nuPed; + double _nuWall; + + /** + * Driving force \f$ F_i =\frac{\mathbf{v_0}-\mathbf{v_i}}{\tau}\$ + * This is a duplicate of @see GCFMModel::ForceDriv + * @param ped Pointer to Pedestrians + * @param room Pointer to Room + * + * + * @return Point + */ + Point ForceDriv(Pedestrian* ped, Room* room) const; + /** + * Repulsive force between two pedestrians ped1 and ped2 according to + * the Gompertz model (unpublished) + * + * @param ped1 Pointer to Pedestrian: First pedestrian + * @param ped2 Pointer to Pedestrian: Second pedestrian + * + * @return Point + */ + Point ForceRepPed(Pedestrian* ped1, Pedestrian* ped2) const; + /** + * Repulsive force acting on pedestrian <ped> from the walls in + * <subroom>. The sum of all repulsive forces of the walls in <subroom> is calculated + * @see ForceRepWall + * @param ped Pointer to Pedestrian + * @param subroom Pointer to SubRoom + * + * @return Point + */ + Point ForceRepRoom(Pedestrian* ped, SubRoom* subroom) const; + /** + * Repulsive force between pedestrian <ped> and wall <l> + * + * @param ped Pointer to Pedestrian + * @param l reference to Wall + * + * @return Point + */ + Point ForceRepWall(Pedestrian* ped, const Wall& l) const; + +public: + + GompertzModel(DirectionStrategy* dir, double nuped, double nuwall); + virtual ~GompertzModel(void); - public: - - GompertzModel(DirectionStrategy* dir, double nuped, double nuwall); - virtual ~GompertzModel(void); - - DirectionStrategy* GetDirection() const; - /** - * Get the parameter for the strength of the ped-PED repulsive force - * - * - * @return double - */ - double GetNuPed() const; - /** - * Get the parameter for the strength of the ped-WALL repulsive force - * - * - * @return - */ - double GetNuWall() const; - virtual void CalculateForce(double time, std::vector< Point >& result_acc, Building* building, - int roomID, int SubRoomID) const; - /** - * Solve the differential equations and update the positions and velocities - * @param t the actual time - * @param tp the next timestep - * @param building the geometry object - */ - virtual void CalculateForceLC(double t, double tp, Building* building) const; - /** - * @return all model parameters in a nicely formatted string - */ - virtual std::string writeParameter() const; + DirectionStrategy* GetDirection() const; + /** + * Get the parameter for the strength of the ped-PED repulsive force + * + * + * @return double + */ + double GetNuPed() const; + /** + * Get the parameter for the strength of the ped-WALL repulsive force + * + * + * @return + */ + double GetNuWall() const; + virtual void CalculateForce(double time, std::vector< Point >& result_acc, Building* building, + int roomID, int SubRoomID) const; + /** + * Solve the differential equations and update the positions and velocities + * @param t the actual time + * @param tp the next timestep + * @param building the geometry object + */ + virtual void CalculateForceLC(double t, double tp, Building* building) const; + /** + * @return all model parameters in a nicely formatted string + */ + virtual std::string writeParameter() const; }; #endif /* _FORCEMODEL_H */ diff --git a/math/Mathematics.cpp b/math/Mathematics.cpp index 419854febca1e0a2c3688c9617b01a88da6d9805..342d372b3a6556cae0a7d1859b4c7c014be2193d 100644 --- a/math/Mathematics.cpp +++ b/math/Mathematics.cpp @@ -38,8 +38,9 @@ using namespace std; * Determines the sign of the number x. * Returns -1 if x is negativ else 1. */ -double sign(double x) { - return (x < 0) ? -1.0 : 1.0; +double sign(double x) +{ + return (x < 0) ? -1.0 : 1.0; } @@ -137,41 +138,43 @@ Y(x) = y1 + dy1*(x-x1) + [x1 x1 x2]y*(x-x1)^2 + [x1 x1 x2 x2]y*(x-x1)^2*(x-x2) // thanks to Sean Curtis -double hermite_interp(double t, double x1, double x2, double y1, double y2, double dy1, double dy2) { - assert( t >= x1 && t <= x2 && "Can only interpolate values inside the range" ); - assert( x2 > x1 && "Intervals must be defined as x1 < x2" ); - - double scale = x2 - x1; - t = ( t - x1 ) / scale; - double t2 = t * t; - double t3 = t2 * t; - double h1 = 2 * t3 - 3 * t2 + 1; - double h2 = -2 * t3 + 3 * t2; - double h3 = t3 - 2 * t2 + t; - double h4 = t3 - t2; - double left = y1 * h1 + dy1 * h3 * scale; - double right = y2 * h2 + dy2 * h4 * scale; - return left + right; +double hermite_interp(double t, double x1, double x2, double y1, double y2, double dy1, double dy2) +{ + assert( t >= x1 && t <= x2 && "Can only interpolate values inside the range" ); + assert( x2 > x1 && "Intervals must be defined as x1 < x2" ); + + double scale = x2 - x1; + t = ( t - x1 ) / scale; + double t2 = t * t; + double t3 = t2 * t; + double h1 = 2 * t3 - 3 * t2 + 1; + double h2 = -2 * t3 + 3 * t2; + double h3 = t3 - 2 * t2 + t; + double h4 = t3 - t2; + double left = y1 * h1 + dy1 * h3 * scale; + double right = y2 * h2 + dy2 * h4 * scale; + return left + right; } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// /* Principal cubic root of a complex number */ -complex<double> c_cbrt(complex<double> x) { - double a, b, r, phi, rn; - complex<double> I(0, 1); - double s; - a = real(x); - b = imag(x); - - r = sqrt(a * a + b * b); - - phi = atan2(b, a); - phi /= 3.0; - rn = cbrt(r); - s = sin(phi); - return rn * cos(phi) + I * rn*s; +complex<double> c_cbrt(complex<double> x) +{ + double a, b, r, phi, rn; + complex<double> I(0, 1); + double s; + a = real(x); + b = imag(x); + + r = sqrt(a * a + b * b); + + phi = atan2(b, a); + phi /= 3.0; + rn = cbrt(r); + s = sin(phi); + return rn * cos(phi) + I * rn*s; } diff --git a/math/ODESolver.cpp b/math/ODESolver.cpp index aacbacca6a4403961b126950dbb658c862cce7e8..760cc303d1b3b030dc870ab48eebf2de76c7d954 100644 --- a/math/ODESolver.cpp +++ b/math/ODESolver.cpp @@ -33,11 +33,13 @@ using namespace std; -ODESolver::ODESolver(ForceModel *model) : model(model) { +ODESolver::ODESolver(ForceModel *model) : model(model) +{ } -EulerSolver::EulerSolver(ForceModel *model) : ODESolver(model) { +EulerSolver::EulerSolver(ForceModel *model) : ODESolver(model) +{ } @@ -51,157 +53,161 @@ EulerSolver::EulerSolver(ForceModel *model) : ODESolver(model) { * - entsprechend werden dann die neuen Gescwindigkeiten und Positionen der Fußgänger gesetzt * */ -void EulerSolver::solveODE(double ti, double tip1, Building* building) const { - double h = tip1 - ti; - vector< vector < vector < Point > > > result_acc_room = vector<vector < vector < Point > > >(); - - // Schleife über alle Räume - for (int i = 0; i < building->GetNumberOfRooms(); i++) { - Room* r = building->GetRoom(i); - vector < vector < Point > > result_acc_rooms = vector < vector < Point > > (); - // Schleife über alle SubRooms im Raum - for (int j = 0; j < r->GetNumberOfSubRooms(); j++) { - SubRoom* s = r->GetSubRoom(j); - int anzpeds = s->GetNumberOfPedestrians(); - vector< Point > result_acc = vector< Point > (); - if (anzpeds != 0) { - model->CalculateForce(ti, result_acc, building, i, s->GetSubRoomID()); - } - result_acc_rooms.push_back(result_acc); - result_acc.clear(); - } - result_acc_room.push_back(result_acc_rooms); - result_acc_rooms.clear(); - } - - /* PRARALLELES UPDATE */ - - // Schleife über alle Räume - for (int i = 0; i < building->GetNumberOfRooms(); i++) { - Room* r = building->GetRoom(i); - // Schleife über alle SubRooms im Raum - for (int j = 0; j < r->GetNumberOfSubRooms(); j++) { - SubRoom* s = r->GetSubRoom(j); - int anzpeds = s->GetNumberOfPedestrians(); - // Schleife über alle Fußgänger im SubRoom - for (int k = 0; k < anzpeds; ++k) { - Point result_acc = result_acc_room[i][j][k]; - Pedestrian* ped = s->GetPedestrian(k); - Point pos_neu, v_neu; // neue Positionen und Geschwindigkeiten setzen - v_neu = (result_acc * h) + ped->GetV(); - if (v_neu.Norm() < J_EPS_V) - pos_neu = ped->GetPos(); - else - pos_neu = (v_neu * h) + ped->GetPos(); - // neue Werte setzten - ped->SetPos(pos_neu); - ped->SetV(v_neu); - ped->SetPhiPed(); - ped->UpdateJamData(); - } - } - } - result_acc_room.clear(); +void EulerSolver::solveODE(double ti, double tip1, Building* building) const +{ + double h = tip1 - ti; + vector< vector < vector < Point > > > result_acc_room = vector<vector < vector < Point > > >(); + + // Schleife über alle Räume + for (int i = 0; i < building->GetNumberOfRooms(); i++) { + Room* r = building->GetRoom(i); + vector < vector < Point > > result_acc_rooms = vector < vector < Point > > (); + // Schleife über alle SubRooms im Raum + for (int j = 0; j < r->GetNumberOfSubRooms(); j++) { + SubRoom* s = r->GetSubRoom(j); + int anzpeds = s->GetNumberOfPedestrians(); + vector< Point > result_acc = vector< Point > (); + if (anzpeds != 0) { + model->CalculateForce(ti, result_acc, building, i, s->GetSubRoomID()); + } + result_acc_rooms.push_back(result_acc); + result_acc.clear(); + } + result_acc_room.push_back(result_acc_rooms); + result_acc_rooms.clear(); + } + + /* PRARALLELES UPDATE */ + + // Schleife über alle Räume + for (int i = 0; i < building->GetNumberOfRooms(); i++) { + Room* r = building->GetRoom(i); + // Schleife über alle SubRooms im Raum + for (int j = 0; j < r->GetNumberOfSubRooms(); j++) { + SubRoom* s = r->GetSubRoom(j); + int anzpeds = s->GetNumberOfPedestrians(); + // Schleife über alle Fußgänger im SubRoom + for (int k = 0; k < anzpeds; ++k) { + Point result_acc = result_acc_room[i][j][k]; + Pedestrian* ped = s->GetPedestrian(k); + Point pos_neu, v_neu; // neue Positionen und Geschwindigkeiten setzen + v_neu = (result_acc * h) + ped->GetV(); + if (v_neu.Norm() < J_EPS_V) + pos_neu = ped->GetPos(); + else + pos_neu = (v_neu * h) + ped->GetPos(); + // neue Werte setzten + ped->SetPos(pos_neu); + ped->SetV(v_neu); + ped->SetPhiPed(); + ped->UpdateJamData(); + } + } + } + result_acc_room.clear(); } -VelocityVerletSolver::VelocityVerletSolver(ForceModel *model) : ODESolver(model) { +VelocityVerletSolver::VelocityVerletSolver(ForceModel *model) : ODESolver(model) +{ }; -void VelocityVerletSolver::solveODE(double ti, double tip1, Building* building) const { - double h = tip1 - ti; - double h2 = h*h; - double lambda = 0.5; - - vector< vector < vector < Point > > > result1_acc_room = vector<vector < vector < Point > > >(); - vector< vector < vector < Point > > > result2_acc_room = vector<vector < vector < Point > > >(); - // Schleife über alle Räume - for (int i = 0; i < building->GetNumberOfRooms(); i++) { - Room* r = building->GetRoom(i); - vector < vector < Point > > result1_acc_subroom = vector < vector < Point > > (); - // Schleife über alle SubRooms im Raum - for (int j = 0; j < r->GetNumberOfSubRooms(); j++) { - SubRoom* s = r->GetSubRoom(j); - int anzpeds = s->GetNumberOfPedestrians(); - vector< Point > result1_acc = vector< Point > (); - if (anzpeds != 0) { - model->CalculateForce(ti, result1_acc, building, i, s->GetSubRoomID()); - } - result1_acc_subroom.push_back(result1_acc); - result1_acc.clear(); - } - result1_acc_room.push_back(result1_acc_subroom); - result1_acc_subroom.clear(); - } - - /* ERSTES PRARALLELES UPDATE */ - - // Schleife über alle Räume - for (int i = 0; i < building->GetNumberOfRooms(); i++) { - Room* r = building->GetRoom(i); - // Schleife über alle SubRooms im Raum - for (int j = 0; j < r->GetNumberOfSubRooms(); j++) { - SubRoom* s = r->GetSubRoom(j); - int anzpeds = s->GetNumberOfPedestrians(); - // Schleife über alle Fußgänger im SubRoom - for (int k = 0; k < anzpeds; ++k) { - Pedestrian* ped = s->GetPedestrian(k); - Point pos_neu, v_neu; // neue Positionen und Geschwindigkeiten setzen - if ((ped->GetV() + result1_acc_room[i][j][k]*0.5 * h).Norm() < J_EPS_V) - pos_neu = ped->GetPos(); - else - pos_neu = ped->GetPos() + ped->GetV() * h + result1_acc_room[i][j][k]*0.5 * h2; - v_neu = ped->GetV() + result1_acc_room[i][j][k] * h * lambda; - ped->SetPos(pos_neu); - ped->SetV(v_neu); - } - } - } - - // Schleife über alle Räume - for (int i = 0; i < building->GetNumberOfRooms(); i++) { - Room* r = building->GetRoom(i); - vector < vector < Point > > result2_acc_subroom = vector < vector < Point > > (); - // Schleife über alle SubRooms im Raum - for (int j = 0; j < r->GetNumberOfSubRooms(); j++) { - SubRoom* s = r->GetSubRoom(j); - int anzpeds = s->GetNumberOfPedestrians(); - vector< Point > result2_acc = vector< Point > (); - if (anzpeds != 0) { - model->CalculateForce(ti, result2_acc, building, i, s->GetSubRoomID()); - } - result2_acc_subroom.push_back(result2_acc); - result2_acc.clear(); - } - result2_acc_room.push_back(result2_acc_subroom); - result2_acc_subroom.clear(); - } - - - /* ZWEITES PRARALLELES UPDATE */ - - // Schleife übr alle Räume - for (int i = 0; i < building->GetNumberOfRooms(); i++) { - Room* r = building->GetRoom(i); - // Schleife über alle SubRooms im Raum - for (int j = 0; j < r->GetNumberOfSubRooms(); j++) { - SubRoom* s = r->GetSubRoom(j); - int anzpeds = s->GetNumberOfPedestrians(); - for (int k = 0; k < anzpeds; ++k) { - Pedestrian* ped = s->GetPedestrian(k); - Point v_neu; // neue Positionen und Geschwindigkeiten setzen - v_neu = ped->GetV() + (result1_acc_room[i][j][k] + result2_acc_room[i][j][k])*0.5 * h; - ped->SetV(v_neu); - ped->SetPhiPed(); - } - } - } - - result1_acc_room.clear(); - result2_acc_room.clear(); +void VelocityVerletSolver::solveODE(double ti, double tip1, Building* building) const +{ + double h = tip1 - ti; + double h2 = h*h; + double lambda = 0.5; + + vector< vector < vector < Point > > > result1_acc_room = vector<vector < vector < Point > > >(); + vector< vector < vector < Point > > > result2_acc_room = vector<vector < vector < Point > > >(); + // Schleife über alle Räume + for (int i = 0; i < building->GetNumberOfRooms(); i++) { + Room* r = building->GetRoom(i); + vector < vector < Point > > result1_acc_subroom = vector < vector < Point > > (); + // Schleife über alle SubRooms im Raum + for (int j = 0; j < r->GetNumberOfSubRooms(); j++) { + SubRoom* s = r->GetSubRoom(j); + int anzpeds = s->GetNumberOfPedestrians(); + vector< Point > result1_acc = vector< Point > (); + if (anzpeds != 0) { + model->CalculateForce(ti, result1_acc, building, i, s->GetSubRoomID()); + } + result1_acc_subroom.push_back(result1_acc); + result1_acc.clear(); + } + result1_acc_room.push_back(result1_acc_subroom); + result1_acc_subroom.clear(); + } + + /* ERSTES PRARALLELES UPDATE */ + + // Schleife über alle Räume + for (int i = 0; i < building->GetNumberOfRooms(); i++) { + Room* r = building->GetRoom(i); + // Schleife über alle SubRooms im Raum + for (int j = 0; j < r->GetNumberOfSubRooms(); j++) { + SubRoom* s = r->GetSubRoom(j); + int anzpeds = s->GetNumberOfPedestrians(); + // Schleife über alle Fußgänger im SubRoom + for (int k = 0; k < anzpeds; ++k) { + Pedestrian* ped = s->GetPedestrian(k); + Point pos_neu, v_neu; // neue Positionen und Geschwindigkeiten setzen + if ((ped->GetV() + result1_acc_room[i][j][k]*0.5 * h).Norm() < J_EPS_V) + pos_neu = ped->GetPos(); + else + pos_neu = ped->GetPos() + ped->GetV() * h + result1_acc_room[i][j][k]*0.5 * h2; + v_neu = ped->GetV() + result1_acc_room[i][j][k] * h * lambda; + ped->SetPos(pos_neu); + ped->SetV(v_neu); + } + } + } + + // Schleife über alle Räume + for (int i = 0; i < building->GetNumberOfRooms(); i++) { + Room* r = building->GetRoom(i); + vector < vector < Point > > result2_acc_subroom = vector < vector < Point > > (); + // Schleife über alle SubRooms im Raum + for (int j = 0; j < r->GetNumberOfSubRooms(); j++) { + SubRoom* s = r->GetSubRoom(j); + int anzpeds = s->GetNumberOfPedestrians(); + vector< Point > result2_acc = vector< Point > (); + if (anzpeds != 0) { + model->CalculateForce(ti, result2_acc, building, i, s->GetSubRoomID()); + } + result2_acc_subroom.push_back(result2_acc); + result2_acc.clear(); + } + result2_acc_room.push_back(result2_acc_subroom); + result2_acc_subroom.clear(); + } + + + /* ZWEITES PRARALLELES UPDATE */ + + // Schleife übr alle Räume + for (int i = 0; i < building->GetNumberOfRooms(); i++) { + Room* r = building->GetRoom(i); + // Schleife über alle SubRooms im Raum + for (int j = 0; j < r->GetNumberOfSubRooms(); j++) { + SubRoom* s = r->GetSubRoom(j); + int anzpeds = s->GetNumberOfPedestrians(); + for (int k = 0; k < anzpeds; ++k) { + Pedestrian* ped = s->GetPedestrian(k); + Point v_neu; // neue Positionen und Geschwindigkeiten setzen + v_neu = ped->GetV() + (result1_acc_room[i][j][k] + result2_acc_room[i][j][k])*0.5 * h; + ped->SetV(v_neu); + ped->SetPhiPed(); + } + } + } + + result1_acc_room.clear(); + result2_acc_room.clear(); }; -LeapfrogSolver::LeapfrogSolver(ForceModel *model) : ODESolver(model) { +LeapfrogSolver::LeapfrogSolver(ForceModel *model) : ODESolver(model) +{ } @@ -215,67 +221,70 @@ LeapfrogSolver::LeapfrogSolver(ForceModel *model) : ODESolver(model) { * - entsprechend werden dann die neuen Gescwindigkeiten und Positionen der Fußgänger gesetzt * */ -void LeapfrogSolver::solveODE(double ti, double tip1, Building* building) const { - double h = tip1 - ti; - vector< vector < vector < Point > > > result_acc_room = vector<vector < vector < Point > > >(); - - // Schleife übr alle Räume - for (int i = 0; i < building->GetNumberOfRooms(); i++) { - Room* r = building->GetRoom(i); - vector < vector < Point > > result_acc_rooms = vector < vector < Point > > (); - // Schleife über alle SubRooms im Raum - for (int j = 0; j < r->GetNumberOfSubRooms(); j++) { - SubRoom* s = r->GetSubRoom(j); - int anzpeds = s->GetNumberOfPedestrians(); - vector< Point > result_acc = vector< Point > (); - if (anzpeds != 0) { - model->CalculateForce(ti, result_acc, building, i, s->GetSubRoomID()); - } - result_acc_rooms.push_back(result_acc); - result_acc.clear(); - } - result_acc_room.push_back(result_acc_rooms); - result_acc_rooms.clear(); - } - - /* PRARALLELES UPDATE */ - - // Schleife übr alle Räume - for (int i = 0; i < building->GetNumberOfRooms(); i++) { - Room* r = building->GetRoom(i); - // Schleife über alle SubRooms im Raum - for (int j = 0; j < r->GetNumberOfSubRooms(); j++) { - SubRoom* s = r->GetSubRoom(j); - int anzpeds = s->GetNumberOfPedestrians(); - // Schleife über alle Fußgänger im SubRoom - for (int k = 0; k < anzpeds; ++k) { - Point result_acc = result_acc_room[i][j][k]; - Pedestrian* ped = s->GetPedestrian(k); - Point pos_neu, v_neu; // neue Positionen und Geschwindigkeiten setzen - if (ti == 0.0) { - v_neu = (result_acc * 0.5 * h) + ped->GetV(); // v(0.5) wird aus v(0) berechnet - } else { - v_neu = (result_acc * h) + ped->GetV(); - } - if (v_neu.Norm() < J_EPS_V) - pos_neu = ped->GetPos(); - else - pos_neu = (v_neu * h) + ped->GetPos(); - // neue Werte setzten - ped->SetPos(pos_neu); - ped->SetV(v_neu); - ped->SetPhiPed(); - } - } - } - result_acc_room.clear(); +void LeapfrogSolver::solveODE(double ti, double tip1, Building* building) const +{ + double h = tip1 - ti; + vector< vector < vector < Point > > > result_acc_room = vector<vector < vector < Point > > >(); + + // Schleife übr alle Räume + for (int i = 0; i < building->GetNumberOfRooms(); i++) { + Room* r = building->GetRoom(i); + vector < vector < Point > > result_acc_rooms = vector < vector < Point > > (); + // Schleife über alle SubRooms im Raum + for (int j = 0; j < r->GetNumberOfSubRooms(); j++) { + SubRoom* s = r->GetSubRoom(j); + int anzpeds = s->GetNumberOfPedestrians(); + vector< Point > result_acc = vector< Point > (); + if (anzpeds != 0) { + model->CalculateForce(ti, result_acc, building, i, s->GetSubRoomID()); + } + result_acc_rooms.push_back(result_acc); + result_acc.clear(); + } + result_acc_room.push_back(result_acc_rooms); + result_acc_rooms.clear(); + } + + /* PRARALLELES UPDATE */ + + // Schleife übr alle Räume + for (int i = 0; i < building->GetNumberOfRooms(); i++) { + Room* r = building->GetRoom(i); + // Schleife über alle SubRooms im Raum + for (int j = 0; j < r->GetNumberOfSubRooms(); j++) { + SubRoom* s = r->GetSubRoom(j); + int anzpeds = s->GetNumberOfPedestrians(); + // Schleife über alle Fußgänger im SubRoom + for (int k = 0; k < anzpeds; ++k) { + Point result_acc = result_acc_room[i][j][k]; + Pedestrian* ped = s->GetPedestrian(k); + Point pos_neu, v_neu; // neue Positionen und Geschwindigkeiten setzen + if (ti == 0.0) { + v_neu = (result_acc * 0.5 * h) + ped->GetV(); // v(0.5) wird aus v(0) berechnet + } else { + v_neu = (result_acc * h) + ped->GetV(); + } + if (v_neu.Norm() < J_EPS_V) + pos_neu = ped->GetPos(); + else + pos_neu = (v_neu * h) + ped->GetPos(); + // neue Werte setzten + ped->SetPos(pos_neu); + ped->SetV(v_neu); + ped->SetPhiPed(); + } + } + } + result_acc_room.clear(); } -EulerSolverLC::EulerSolverLC(ForceModel *model) : ODESolver(model) { +EulerSolverLC::EulerSolverLC(ForceModel *model) : ODESolver(model) +{ } -void EulerSolverLC::solveODE(double ti, double tip1, Building* building) const { +void EulerSolverLC::solveODE(double ti, double tip1, Building* building) const +{ - model->CalculateForceLC(ti, tip1, building); + model->CalculateForceLC(ti, tip1, building); } diff --git a/math/ODESolver.h b/math/ODESolver.h index 9d3b5fec57c649561803165cf15f1f8a22d55ab6..eb79d7d9235b957eea932984f0a99575ec0b4b59 100644 --- a/math/ODESolver.h +++ b/math/ODESolver.h @@ -38,12 +38,12 @@ class Building; * General template for ODE solvers */ class ODESolver { - protected: - ForceModel *model; - public: - ODESolver(ForceModel* model); - virtual ~ODESolver(){}; - virtual void solveODE(double t, double tp, Building* building) const = 0; +protected: + ForceModel *model; +public: + ODESolver(ForceModel* model); + virtual ~ODESolver() {}; + virtual void solveODE(double t, double tp, Building* building) const = 0; }; @@ -51,9 +51,9 @@ class ODESolver { * Implementation of the explicit Euler method for solving different equations. */ class EulerSolver : public ODESolver { - public: - EulerSolver(ForceModel *model); - virtual void solveODE(double t, double tp, Building* building) const; +public: + EulerSolver(ForceModel *model); + virtual void solveODE(double t, double tp, Building* building) const; }; @@ -61,25 +61,25 @@ class EulerSolver : public ODESolver { * Implementation of the Velocity - Verlet method */ class VelocityVerletSolver : public ODESolver { - public: - VelocityVerletSolver(ForceModel *model); - virtual void solveODE(double t, double tp, Building* building) const; +public: + VelocityVerletSolver(ForceModel *model); + virtual void solveODE(double t, double tp, Building* building) const; }; /** * Implementation of the LeapFrog algorithm */ class LeapfrogSolver : public ODESolver { - public: - LeapfrogSolver(ForceModel *model); - virtual void solveODE(double t, double tp, Building* building) const; +public: + LeapfrogSolver(ForceModel *model); + virtual void solveODE(double t, double tp, Building* building) const; }; class EulerSolverLC : public ODESolver { - public: - EulerSolverLC(ForceModel *model); - virtual void solveODE(double t, double tp, Building* building) const; +public: + EulerSolverLC(ForceModel *model); + virtual void solveODE(double t, double tp, Building* building) const; }; diff --git a/mpi/LCGrid.cpp b/mpi/LCGrid.cpp index 1b4cc70816e27c3ddfe453d003b94dfa613ac725..43fc7858df3525102f848a527f84eb6d779d090e 100644 --- a/mpi/LCGrid.cpp +++ b/mpi/LCGrid.cpp @@ -45,247 +45,258 @@ using namespace std; -LCGrid::LCGrid(double boundaries[4], double cellsize, int nPeds){ +LCGrid::LCGrid(double boundaries[4], double cellsize, int nPeds) +{ - pGrid_xmin=boundaries[0]; - pGrid_xmax=boundaries[1]; - pGrid_ymin=boundaries[2]; - pGrid_ymax=boundaries[3]; - pCellSize=cellsize; - pNpeds=nPeds; + pGrid_xmin=boundaries[0]; + pGrid_xmax=boundaries[1]; + pGrid_ymin=boundaries[2]; + pGrid_ymax=boundaries[3]; + pCellSize=cellsize; + pNpeds=nPeds; - // add 1 to ensure that the whole area is covered by cells if not divisable without remainder - pGridSizeX = (int) ((pGrid_xmax - pGrid_xmin) / pCellSize) + 1 + 2; // 1 dummy cell on each side - pGridSizeY = (int) ((pGrid_ymax - pGrid_ymin) / pCellSize) + 1 + 2; // 1 dummy cell on each side + // add 1 to ensure that the whole area is covered by cells if not divisable without remainder + pGridSizeX = (int) ((pGrid_xmax - pGrid_xmin) / pCellSize) + 1 + 2; // 1 dummy cell on each side + pGridSizeY = (int) ((pGrid_ymax - pGrid_ymin) / pCellSize) + 1 + 2; // 1 dummy cell on each side - // allocate memory for cells (2D-array) and initialize - pCellHead= new int *[pGridSizeY]; + // allocate memory for cells (2D-array) and initialize + pCellHead= new int *[pGridSizeY]; - for (int i = 0; i < pGridSizeY; ++i) { - pCellHead[i] = new int[pGridSizeX]; // nx columns + for (int i = 0; i < pGridSizeY; ++i) { + pCellHead[i] = new int[pGridSizeX]; // nx columns - for (int j = 0; j < pGridSizeX; ++j) { - pCellHead[i][j] = LIST_EMPTY; - } - } + for (int j = 0; j < pGridSizeX; ++j) { + pCellHead[i][j] = LIST_EMPTY; + } + } - // creating and resetting the pedestrians list - pList = new int[nPeds]; - for(int i=0;i<nPeds;i++) pList[i]=0; + // creating and resetting the pedestrians list + pList = new int[nPeds]; + for(int i=0; i<nPeds; i++) pList[i]=0; - //allocating the place for the peds copy - pLocalPedsCopy=new Pedestrian*[nPeds]; - for(int i=0;i<nPeds;i++) pLocalPedsCopy[i]=NULL; + //allocating the place for the peds copy + pLocalPedsCopy=new Pedestrian*[nPeds]; + for(int i=0; i<nPeds; i++) pLocalPedsCopy[i]=NULL; } -LCGrid::~LCGrid(){ - for(int i=0;i<pNpeds;i++) { - if(!pLocalPedsCopy[i]) - delete pLocalPedsCopy[i]; - } - delete [] pList; - delete [] pLocalPedsCopy; - for (int i = 0; i < pGridSizeY; ++i) delete[] pCellHead[i]; - delete[] pCellHead; +LCGrid::~LCGrid() +{ + for(int i=0; i<pNpeds; i++) { + if(!pLocalPedsCopy[i]) + delete pLocalPedsCopy[i]; + } + delete [] pList; + delete [] pLocalPedsCopy; + for (int i = 0; i < pGridSizeY; ++i) delete[] pCellHead[i]; + delete[] pCellHead; } -void LCGrid::ShallowCopy(const vector<Pedestrian*>& peds){ +void LCGrid::ShallowCopy(const vector<Pedestrian*>& peds) +{ - for(unsigned int p=0;p<peds.size();p++){ - int id= peds[p]->GetID()-1; - pLocalPedsCopy[id]=peds[p]; - } + for(unsigned int p=0; p<peds.size(); p++) { + int id= peds[p]->GetID()-1; + pLocalPedsCopy[id]=peds[p]; + } } -void LCGrid::Update(const vector<Pedestrian*>& peds){ - int nSize=peds.size(); - - ClearGrid(); - - for (int p = 0; p < nSize; p++) { - Pedestrian* ped = peds[p]; - int id=ped->GetID()-1; - // determine the cell coordinates of pedestrian i - int ix = (int) ((ped->GetPos().GetX() - pGrid_xmin) / pCellSize) + 1; // +1 because of dummy cells - int iy = (int) ((ped->GetPos().GetY() - pGrid_ymin) / pCellSize) + 1; - //printf("[%f, %f] ",ped->GetPos().GetX(), ped->GetPos().GetY()); - // create lists - //printf("[%d=%d] ",ped->GetPedIndex(),id); - pList[id] = pCellHead[iy][ix]; - pCellHead[iy][ix] = id; - - pLocalPedsCopy[id]=ped; - } +void LCGrid::Update(const vector<Pedestrian*>& peds) +{ + int nSize=peds.size(); + + ClearGrid(); + + for (int p = 0; p < nSize; p++) { + Pedestrian* ped = peds[p]; + int id=ped->GetID()-1; + // determine the cell coordinates of pedestrian i + int ix = (int) ((ped->GetPos().GetX() - pGrid_xmin) / pCellSize) + 1; // +1 because of dummy cells + int iy = (int) ((ped->GetPos().GetY() - pGrid_ymin) / pCellSize) + 1; + //printf("[%f, %f] ",ped->GetPos().GetX(), ped->GetPos().GetY()); + // create lists + //printf("[%d=%d] ",ped->GetPedIndex(),id); + pList[id] = pCellHead[iy][ix]; + pCellHead[iy][ix] = id; + + pLocalPedsCopy[id]=ped; + } } // I hope you had called Clear() first -void LCGrid::Update(Pedestrian* ped){ +void LCGrid::Update(Pedestrian* ped) +{ - int id=ped->GetID()-1; - // determine the cell coordinates of pedestrian i - int ix = (int) ((ped->GetPos().GetX() - pGrid_xmin) / pCellSize) + 1; // +1 because of dummy cells - int iy = (int) ((ped->GetPos().GetY() - pGrid_ymin) / pCellSize) + 1; + int id=ped->GetID()-1; + // determine the cell coordinates of pedestrian i + int ix = (int) ((ped->GetPos().GetX() - pGrid_xmin) / pCellSize) + 1; // +1 because of dummy cells + int iy = (int) ((ped->GetPos().GetY() - pGrid_ymin) / pCellSize) + 1; - // update the list previously created - pList[id] = pCellHead[iy][ix]; - pCellHead[iy][ix] = id; + // update the list previously created + pList[id] = pCellHead[iy][ix]; + pCellHead[iy][ix] = id; - // this is probably a pedestrian coming from the mpi routine, so made a copy - pLocalPedsCopy[id]=ped; + // this is probably a pedestrian coming from the mpi routine, so made a copy + pLocalPedsCopy[id]=ped; } -void LCGrid::ClearGrid(){ - // start by resetting the current list - for (int i = 0; i < pGridSizeY; ++i) { - for (int j = 0; j < pGridSizeX; ++j) { - pCellHead[i][j] = LIST_EMPTY; - } - } +void LCGrid::ClearGrid() +{ + // start by resetting the current list + for (int i = 0; i < pGridSizeY; ++i) { + for (int j = 0; j < pGridSizeX; ++j) { + pCellHead[i][j] = LIST_EMPTY; + } + } - for(int i=0;i<pNpeds;i++) pList[i]=LIST_EMPTY; + for(int i=0; i<pNpeds; i++) pList[i]=LIST_EMPTY; } -void LCGrid::GetNeighbourhood(const Pedestrian* ped, Pedestrian** neighbourhood, int* nSize){ - - double xPed=ped->GetPos().GetX(); - double yPed=ped->GetPos().GetY(); - - - int l = (int) ((xPed - pGrid_xmin) / pCellSize) + 1; // +1 because of dummy cells - int k = (int) ((yPed - pGrid_ymin) / pCellSize) + 1; - - //-1 to get correct mapping in the array local - int myID=ped->GetID()-1; - - *nSize=0; - // all neighbor cells - for (int i = l - 1; i <= l + 1; ++i) { - for (int j = k - 1; j <= k + 1; ++j) { - //printf(" i=%d j=%d k=%d l=%d\n",i,j,nx,ny); - int p = pCellHead[j][i]; - // all peds in one cell - while (p != LIST_EMPTY) { - double x=pLocalPedsCopy[p]->GetPos().GetX(); - double y=pLocalPedsCopy[p]->GetPos().GetY(); - double dist=((x-xPed)*(x-xPed) + (y-yPed)*(y-yPed)); - if((dist<pCellSize*pCellSize) && (p!=myID)){ - neighbourhood[(*nSize)++]=pLocalPedsCopy[p]; - } - // next ped - p = pList[p]; - } - } - } +void LCGrid::GetNeighbourhood(const Pedestrian* ped, Pedestrian** neighbourhood, int* nSize) +{ + + double xPed=ped->GetPos().GetX(); + double yPed=ped->GetPos().GetY(); + + + int l = (int) ((xPed - pGrid_xmin) / pCellSize) + 1; // +1 because of dummy cells + int k = (int) ((yPed - pGrid_ymin) / pCellSize) + 1; + + //-1 to get correct mapping in the array local + int myID=ped->GetID()-1; + + *nSize=0; + // all neighbor cells + for (int i = l - 1; i <= l + 1; ++i) { + for (int j = k - 1; j <= k + 1; ++j) { + //printf(" i=%d j=%d k=%d l=%d\n",i,j,nx,ny); + int p = pCellHead[j][i]; + // all peds in one cell + while (p != LIST_EMPTY) { + double x=pLocalPedsCopy[p]->GetPos().GetX(); + double y=pLocalPedsCopy[p]->GetPos().GetY(); + double dist=((x-xPed)*(x-xPed) + (y-yPed)*(y-yPed)); + if((dist<pCellSize*pCellSize) && (p!=myID)) { + neighbourhood[(*nSize)++]=pLocalPedsCopy[p]; + } + // next ped + p = pList[p]; + } + } + } } -void LCGrid::GetNeighbourhood(const Pedestrian* ped, vector<Pedestrian*>& neighbourhood){ - - double xPed=ped->GetPos().GetX(); - double yPed=ped->GetPos().GetY(); - - int l = (int) ((xPed - pGrid_xmin) / pCellSize) + 1; // +1 because of dummy cells - int k = (int) ((yPed - pGrid_ymin) / pCellSize) + 1; - - //-1 to get correct mapping in the array local - int myID=ped->GetID()-1; - - // all neighbor cells - for (int i = l - 1; i <= l + 1; ++i) { - for (int j = k - 1; j <= k + 1; ++j) { - //printf(" i=%d j=%d k=%d l=%d\n",i,j,nx,ny); - int p = pCellHead[j][i]; - // all peds in one cell - while (p != LIST_EMPTY) { - double x=pLocalPedsCopy[p]->GetPos().GetX(); - double y=pLocalPedsCopy[p]->GetPos().GetY(); - double dist=((x-xPed)*(x-xPed) + (y-yPed)*(y-yPed)); - if((dist<pCellSize*pCellSize) && (p!=myID)){ - neighbourhood.push_back(pLocalPedsCopy[p]); - } - // next ped - p = pList[p]; - } - } - } +void LCGrid::GetNeighbourhood(const Pedestrian* ped, vector<Pedestrian*>& neighbourhood) +{ + + double xPed=ped->GetPos().GetX(); + double yPed=ped->GetPos().GetY(); + + int l = (int) ((xPed - pGrid_xmin) / pCellSize) + 1; // +1 because of dummy cells + int k = (int) ((yPed - pGrid_ymin) / pCellSize) + 1; + + //-1 to get correct mapping in the array local + int myID=ped->GetID()-1; + + // all neighbor cells + for (int i = l - 1; i <= l + 1; ++i) { + for (int j = k - 1; j <= k + 1; ++j) { + //printf(" i=%d j=%d k=%d l=%d\n",i,j,nx,ny); + int p = pCellHead[j][i]; + // all peds in one cell + while (p != LIST_EMPTY) { + double x=pLocalPedsCopy[p]->GetPos().GetX(); + double y=pLocalPedsCopy[p]->GetPos().GetY(); + double dist=((x-xPed)*(x-xPed) + (y-yPed)*(y-yPed)); + if((dist<pCellSize*pCellSize) && (p!=myID)) { + neighbourhood.push_back(pLocalPedsCopy[p]); + } + // next ped + p = pList[p]; + } + } + } } -void LCGrid::GetNeighbourhood(const Point& pt, vector<Pedestrian*>& neighbourhood){ - double xPed=pt.GetX(); - double yPed=pt.GetY(); - - - int l = (int) ((xPed - pGrid_xmin) / pCellSize) + 1; // +1 because of dummy cells - int k = (int) ((yPed - pGrid_ymin) / pCellSize) + 1; - - // all neighbor cells - for (int i = l - 1; i <= l + 1; ++i) { - for (int j = k - 1; j <= k + 1; ++j) { - //printf(" i=%d j=%d k=%d l=%d\n",i,j,nx,ny); - int p = pCellHead[j][i]; - // all peds in one cell - while (p != LIST_EMPTY) { - double x=pLocalPedsCopy[p]->GetPos().GetX(); - double y=pLocalPedsCopy[p]->GetPos().GetY(); - double dist=((x-xPed)*(x-xPed) + (y-yPed)*(y-yPed)); - if((dist<pCellSize*pCellSize)){ - neighbourhood.push_back(pLocalPedsCopy[p]); - } - // next ped - p = pList[p]; - } - } - } +void LCGrid::GetNeighbourhood(const Point& pt, vector<Pedestrian*>& neighbourhood) +{ + double xPed=pt.GetX(); + double yPed=pt.GetY(); + + + int l = (int) ((xPed - pGrid_xmin) / pCellSize) + 1; // +1 because of dummy cells + int k = (int) ((yPed - pGrid_ymin) / pCellSize) + 1; + + // all neighbor cells + for (int i = l - 1; i <= l + 1; ++i) { + for (int j = k - 1; j <= k + 1; ++j) { + //printf(" i=%d j=%d k=%d l=%d\n",i,j,nx,ny); + int p = pCellHead[j][i]; + // all peds in one cell + while (p != LIST_EMPTY) { + double x=pLocalPedsCopy[p]->GetPos().GetX(); + double y=pLocalPedsCopy[p]->GetPos().GetY(); + double dist=((x-xPed)*(x-xPed) + (y-yPed)*(y-yPed)); + if((dist<pCellSize*pCellSize)) { + neighbourhood.push_back(pLocalPedsCopy[p]); + } + // next ped + p = pList[p]; + } + } + } } -void LCGrid::Dump(){ - - for(int l =1;l<pGridSizeY-1;l++){ - for(int k=1;k<pGridSizeX-1;k++){ - - int ped = pCellHead[l][k]; - - if(ped==LIST_EMPTY) continue; - - printf("Cell[%d][%d] = { ",l,k); - // all neighbor cells - for (int i = l - 1; i <= l + 1; ++i) { - for (int j = k - 1; j <= k + 1; ++j) { - // dummy cells will be empty - int p = pCellHead[i][j]; - // all peds in one cell - while (p != LIST_EMPTY) { - printf("%d, ",p+1); - // next ped - p = pList[p]; - } - } - } - printf("}\n"); - } - } +void LCGrid::Dump() +{ + + for(int l =1; l<pGridSizeY-1; l++) { + for(int k=1; k<pGridSizeX-1; k++) { + + int ped = pCellHead[l][k]; + + if(ped==LIST_EMPTY) continue; + + printf("Cell[%d][%d] = { ",l,k); + // all neighbor cells + for (int i = l - 1; i <= l + 1; ++i) { + for (int j = k - 1; j <= k + 1; ++j) { + // dummy cells will be empty + int p = pCellHead[i][j]; + // all peds in one cell + while (p != LIST_EMPTY) { + printf("%d, ",p+1); + // next ped + p = pList[p]; + } + } + } + printf("}\n"); + } + } } -void LCGrid::dumpCellsOnly(){ - for(int l =1;l<pGridSizeY-1;l++){ - for(int k=1;k<pGridSizeX-1;k++){ - - int ped = pCellHead[l][k]; - - if(ped==LIST_EMPTY) continue; - - printf("Cell[%d][%d] = { ",l,k); - - // all neighbor cells - // dummy cells will be empty - int p = pCellHead[l][k]; - // all peds in one cell - while (p != LIST_EMPTY) { - printf("%d, ",p+1); - // next ped - p = pList[p]; - } - printf("}\n"); - } - } +void LCGrid::dumpCellsOnly() +{ + for(int l =1; l<pGridSizeY-1; l++) { + for(int k=1; k<pGridSizeX-1; k++) { + + int ped = pCellHead[l][k]; + + if(ped==LIST_EMPTY) continue; + + printf("Cell[%d][%d] = { ",l,k); + + // all neighbor cells + // dummy cells will be empty + int p = pCellHead[l][k]; + // all peds in one cell + while (p != LIST_EMPTY) { + printf("%d, ",p+1); + // next ped + p = pList[p]; + } + printf("}\n"); + } + } } diff --git a/mpi/LCGrid.h b/mpi/LCGrid.h index 4e00d8c84acfb2e8bfd2cbb47a9d326ecaea03b3..3f21f7f51a538f10dd5dd478a583a31c3a86e978 100644 --- a/mpi/LCGrid.h +++ b/mpi/LCGrid.h @@ -50,100 +50,100 @@ class Pedestrian; class LCGrid { - private: - - /// the 'first' pedestrian in each cell - int **pCellHead; - /// the next pedestrians. more efficient than the double linked- list - int *pList; - /// number of cells in x- and y-direction respectively. - /// Also to be interpreted as cell coordinates in the grid - int pGridSizeX, pGridSizeY; - /// the cell size default to 2.2 metres - double pCellSize; - /// rectangular area for linked cells which covers the whole geometry - double pGrid_xmin, pGrid_xmax, pGrid_ymin, pGrid_ymax; - /// for convenience - /// will be delete in next versions - Pedestrian** pLocalPedsCopy; - - ///total number of pedestrians - int pNpeds; - - - public: - - - /** - * Constructor - * @param boundaries the boundaries of the grid [xmin xmax ymin ymax] - * @param cellsize the cell size - * @param nPeds the number of pedestrians - */ - LCGrid(double boundaries[4], double cellsize, int nPeds); - - /** - * Desctructor - */ - ~LCGrid(); - - /** - *Update the cells occupation - */ - - void Update(Pedestrian** peds); - /** - *Update the cells occupation - */ - void Update(const std::vector<Pedestrian*>& peds); - - /** - * Update this special pedestrian on the grid - */ - void Update(Pedestrian* ped); - - /** - * Make a shallow copy of the initial pedestrians distribution - */ - void ShallowCopy(const std::vector<Pedestrian*>& peds); - - /** - * Clear the grid. - */ - void ClearGrid(); - - /** - * Dump the content of the cells, output cells and corresponding pedestrians information - */ - void Dump(); - - /** - * Dump the cells positions - */ - void dumpCellsOnly(); - - /** - * Return a vector containing the neighbourhood of the pedestrians ped - * @param ped the considered pedestrian - * @param neighborhood an array containing the pedestrians - * @param nSize the number of returned pedestrians - */ - void GetNeighbourhood(const Pedestrian* ped, Pedestrian** neighborhood, int* nSize); - - - /** - * Return the pedestrians in the neighborhood of a specific location - * @param position - * @param neighbourhood - */ - void GetNeighbourhood(const Point& position, std::vector<Pedestrian*>& neighbourhood); - - /** - * Returns neighbourhood of the pedestrians ped - * @param ped - * @param neighbourhood - */ - void GetNeighbourhood(const Pedestrian* ped, std::vector<Pedestrian*>& neighbourhood); +private: + + /// the 'first' pedestrian in each cell + int **pCellHead; + /// the next pedestrians. more efficient than the double linked- list + int *pList; + /// number of cells in x- and y-direction respectively. + /// Also to be interpreted as cell coordinates in the grid + int pGridSizeX, pGridSizeY; + /// the cell size default to 2.2 metres + double pCellSize; + /// rectangular area for linked cells which covers the whole geometry + double pGrid_xmin, pGrid_xmax, pGrid_ymin, pGrid_ymax; + /// for convenience + /// will be delete in next versions + Pedestrian** pLocalPedsCopy; + + ///total number of pedestrians + int pNpeds; + + +public: + + + /** + * Constructor + * @param boundaries the boundaries of the grid [xmin xmax ymin ymax] + * @param cellsize the cell size + * @param nPeds the number of pedestrians + */ + LCGrid(double boundaries[4], double cellsize, int nPeds); + + /** + * Desctructor + */ + ~LCGrid(); + + /** + *Update the cells occupation + */ + + void Update(Pedestrian** peds); + /** + *Update the cells occupation + */ + void Update(const std::vector<Pedestrian*>& peds); + + /** + * Update this special pedestrian on the grid + */ + void Update(Pedestrian* ped); + + /** + * Make a shallow copy of the initial pedestrians distribution + */ + void ShallowCopy(const std::vector<Pedestrian*>& peds); + + /** + * Clear the grid. + */ + void ClearGrid(); + + /** + * Dump the content of the cells, output cells and corresponding pedestrians information + */ + void Dump(); + + /** + * Dump the cells positions + */ + void dumpCellsOnly(); + + /** + * Return a vector containing the neighbourhood of the pedestrians ped + * @param ped the considered pedestrian + * @param neighborhood an array containing the pedestrians + * @param nSize the number of returned pedestrians + */ + void GetNeighbourhood(const Pedestrian* ped, Pedestrian** neighborhood, int* nSize); + + + /** + * Return the pedestrians in the neighborhood of a specific location + * @param position + * @param neighbourhood + */ + void GetNeighbourhood(const Point& position, std::vector<Pedestrian*>& neighbourhood); + + /** + * Returns neighbourhood of the pedestrians ped + * @param ped + * @param neighbourhood + */ + void GetNeighbourhood(const Pedestrian* ped, std::vector<Pedestrian*>& neighbourhood); }; diff --git a/pedestrian/Ellipse.cpp b/pedestrian/Ellipse.cpp index f45b95ff662e7054e96c4e8ac8d894191aa01a5b..22f91cca197c78f0d9c78683fb5ee430a56a185a 100644 --- a/pedestrian/Ellipse.cpp +++ b/pedestrian/Ellipse.cpp @@ -37,30 +37,32 @@ using namespace std; Konstruktoren ************************************************************/ -JEllipse::JEllipse() { - _vel = Point(); // velocity vector - _center = Point(); // cartesian coordinates of the center - _cosPhi = 1; // = cos(0) - _sinPhi = 0; // = sin(0) - _Xp = 0; //x Ellipse-coord of the centre (Center in (xc,yc) ) - _Amin = 0.18; // Semi-axis in direction of motion: pAmin + V * pAv - _Av = 0.53; - _Bmin = 0.20; // Semi-axis in direction of shoulders: pBmax - V *[(pBmax - pBmin) / V0] - _Bmax = 0.25; - __vel0 = 0; // desired speed -} - -JEllipse::JEllipse(const JEllipse& orig) { - _vel = orig.GetV(); // velocity vector - _center = orig.GetCenter(); - _cosPhi = orig.GetCosPhi(); - _sinPhi = orig.GetSinPhi(); - _Xp = orig.GetXp(); //x Ellipse-coord of the centre (Center in (xc,yc) ) - _Amin = orig.GetAmin(); // Semi-axis in direction of motion: pAmin + V * pAv - _Av = orig.GetAv(); - _Bmin = orig.GetBmin(); // Semi-axis in direction of shoulders: pBmax - V *[(pBmax - pBmin) / V0] - _Bmax = orig.GetBmax(); - __vel0 = orig.GetV0(); // desired speed +JEllipse::JEllipse() +{ + _vel = Point(); // velocity vector + _center = Point(); // cartesian coordinates of the center + _cosPhi = 1; // = cos(0) + _sinPhi = 0; // = sin(0) + _Xp = 0; //x Ellipse-coord of the centre (Center in (xc,yc) ) + _Amin = 0.18; // Semi-axis in direction of motion: pAmin + V * pAv + _Av = 0.53; + _Bmin = 0.20; // Semi-axis in direction of shoulders: pBmax - V *[(pBmax - pBmin) / V0] + _Bmax = 0.25; + __vel0 = 0; // desired speed +} + +JEllipse::JEllipse(const JEllipse& orig) +{ + _vel = orig.GetV(); // velocity vector + _center = orig.GetCenter(); + _cosPhi = orig.GetCosPhi(); + _sinPhi = orig.GetSinPhi(); + _Xp = orig.GetXp(); //x Ellipse-coord of the centre (Center in (xc,yc) ) + _Amin = orig.GetAmin(); // Semi-axis in direction of motion: pAmin + V * pAv + _Av = orig.GetAv(); + _Bmin = orig.GetBmin(); // Semi-axis in direction of shoulders: pBmax - V *[(pBmax - pBmin) / V0] + _Bmax = orig.GetBmax(); + __vel0 = orig.GetV0(); // desired speed } @@ -68,106 +70,129 @@ JEllipse::JEllipse(const JEllipse& orig) { Setter-Funktionen ************************************************************/ -void JEllipse::SetV(const Point& v) { - _vel = v; +void JEllipse::SetV(const Point& v) +{ + _vel = v; } -void JEllipse::SetCenter(Point pos) { - _center = pos; +void JEllipse::SetCenter(Point pos) +{ + _center = pos; } -void JEllipse::SetCosPhi(double c) { - _cosPhi = c; +void JEllipse::SetCosPhi(double c) +{ + _cosPhi = c; } -void JEllipse::SetSinPhi(double s) { - _sinPhi = s; +void JEllipse::SetSinPhi(double s) +{ + _sinPhi = s; } -void JEllipse::SetXp(double xp) { - _Xp = xp; +void JEllipse::SetXp(double xp) +{ + _Xp = xp; } -void JEllipse::SetAmin(double a_min) { - _Amin = a_min; +void JEllipse::SetAmin(double a_min) +{ + _Amin = a_min; } -void JEllipse::SetAv(double a_v) { - _Av = a_v; +void JEllipse::SetAv(double a_v) +{ + _Av = a_v; } -void JEllipse::SetBmin(double b_min) { - _Bmin = b_min; +void JEllipse::SetBmin(double b_min) +{ + _Bmin = b_min; } -void JEllipse::SetBmax(double b_max) { - _Bmax = b_max; +void JEllipse::SetBmax(double b_max) +{ + _Bmax = b_max; } -void JEllipse::SetV0(double v0) { - __vel0 = v0; +void JEllipse::SetV0(double v0) +{ + __vel0 = v0; } /************************************************************* Getter-Funktionen ************************************************************/ -const Point& JEllipse::GetV() const { - return _vel; +const Point& JEllipse::GetV() const +{ + return _vel; } -const Point& JEllipse::GetCenter() const { - return _center; +const Point& JEllipse::GetCenter() const +{ + return _center; } -double JEllipse::GetCosPhi() const { - return _cosPhi; +double JEllipse::GetCosPhi() const +{ + return _cosPhi; } -double JEllipse::GetSinPhi() const { - return _sinPhi; +double JEllipse::GetSinPhi() const +{ + return _sinPhi; } -double JEllipse::GetXp() const { - return _Xp; +double JEllipse::GetXp() const +{ + return _Xp; } -double JEllipse::GetAmin() const { - return _Amin; +double JEllipse::GetAmin() const +{ + return _Amin; } -double JEllipse::GetAv() const { - return _Av; +double JEllipse::GetAv() const +{ + return _Av; } -double JEllipse::GetBmin() const { - return _Bmin; +double JEllipse::GetBmin() const +{ + return _Bmin; } -double JEllipse::GetBmax() const { - return _Bmax; +double JEllipse::GetBmax() const +{ + return _Bmax; } -double JEllipse::GetV0() const { - return __vel0; +double JEllipse::GetV0() const +{ + return __vel0; } -double JEllipse::GetArea() const { - double x = (_Bmax - _Bmin) / __vel0; - double V = _vel.Norm(); - double ea = _Amin + V * _Av; - double eb = _Bmax - V * x; - return ea * eb * M_PI; +double JEllipse::GetArea() const +{ + double x = (_Bmax - _Bmin) / __vel0; + double V = _vel.Norm(); + double ea = _Amin + V * _Av; + double eb = _Bmax - V * x; + return ea * eb * M_PI; } // ellipse semi-axis in the direction of the velocity - double JEllipse::GetEA() const { - return _Amin + _vel.Norm() * _Av; - } +double JEllipse::GetEA() const +{ + return _Amin + _vel.Norm() * _Av; +} // ellipse semi-axis in the orthogonal direction of the velocity -double JEllipse::GetEB() const { - double x = (_Bmax - _Bmin) / __vel0; - return _Bmax - _vel.Norm() * x; +double JEllipse::GetEB() const +{ + double x = (_Bmax - _Bmin) / __vel0; + return _Bmax - _vel.Norm() * x; } @@ -227,17 +252,18 @@ double JEllipse::GetEB() const { output: - return: Effective distance between E1 and E2. By overlaping the distance is negative - - (call by reference) distance between centers + - (call by reference) distance between centers */ -//Time old version: 230000 clicks (0.230000 seconds). +//Time old version: 230000 clicks (0.230000 seconds). //Time new: 180000 clicks (0.180000 seconds) - double JEllipse::EffectiveDistanceToEllipse(const JEllipse& E2, double* dist) const { - // E1 ist Objekt auf dem aufgerufen wird +double JEllipse::EffectiveDistanceToEllipse(const JEllipse& E2, double* dist) const +{ + // E1 ist Objekt auf dem aufgerufen wird Point E1center = this->GetCenter(); Point E2center = E2.GetCenter(); Point R1, R2; - Point E1inE2, //center of E1 in coordinate system of E2 - E2inE1; + Point E1inE2, //center of E1 in coordinate system of E2 + E2inE1; E2inE1 = E2center.CoordTransToEllipse(this->GetCenter(), this->GetCosPhi(), this->GetSinPhi()); E1inE2 = E1center.CoordTransToEllipse(E2.GetCenter(), E2.GetCosPhi(), @@ -248,40 +274,41 @@ double JEllipse::GetEB() const { R2 = E2.PointOnEllipse(E1inE2); //effective distance return *dist - (E1center - R1).Norm() - (E2center - R2).Norm(); -} +} // // input: P is a point in the ellipse world. // output: The point on the ellipse (in cartesian coord) that lays on the same line OP // O being the center of the ellipse -// if P approx equal to Center of ellipse return cartesian coordinats of the point (a,0)/ellipse -Point JEllipse::PointOnEllipse(const Point& P) const { - double x = P.GetX(), y = P.GetY(); - double r = x*x + y*y; - if ( r < J_EPS*J_EPS) - { - //return _center; - Point CP(this->GetEA(), 0); - return CP.CoordTransToCart(this->GetCenter(), this->GetCosPhi(), - this->GetSinPhi()); - } - r = sqrt(r); - - double cosTheta = x/r; - double sinTheta = y/r; - double a = GetEA(); - double b = GetEB(); - Point S; - S.SetX(a*cosTheta); - S.SetY(b*sinTheta); - return S.CoordTransToCart(_center, _cosPhi, _sinPhi); -} - -double JEllipse::EffectiveDistanceToLine(const Line& l) const { - Point C = this->GetCenter(); - Point P = l.ShortestPoint(C); - Point R = this->PointOnEllipse(P); - return (P-R).Norm(); +// if P approx equal to Center of ellipse return cartesian coordinats of the point (a,0)/ellipse +Point JEllipse::PointOnEllipse(const Point& P) const +{ + double x = P.GetX(), y = P.GetY(); + double r = x*x + y*y; + if ( r < J_EPS*J_EPS) { + //return _center; + Point CP(this->GetEA(), 0); + return CP.CoordTransToCart(this->GetCenter(), this->GetCosPhi(), + this->GetSinPhi()); + } + r = sqrt(r); + + double cosTheta = x/r; + double sinTheta = y/r; + double a = GetEA(); + double b = GetEB(); + Point S; + S.SetX(a*cosTheta); + S.SetY(b*sinTheta); + return S.CoordTransToCart(_center, _cosPhi, _sinPhi); +} + +double JEllipse::EffectiveDistanceToLine(const Line& l) const +{ + Point C = this->GetCenter(); + Point P = l.ShortestPoint(C); + Point R = this->PointOnEllipse(P); + return (P-R).Norm(); } // thanks to Sean Curtis. see manuals/Ellipsen/ellipseLineSean.pdf @@ -440,36 +467,39 @@ double JEllipse::EffectiveDistanceToLine(const Line& l) const { // } // check if point given in the ellipse coordinates is inside an ellipse -bool JEllipse::IsInside(const Point& p) const { - double a = GetEA(); - double b = GetEB(); - double x = p.GetX(); - double y = p.GetY(); - double condition = (x * x) / (a * a) + (y * y) / (b * b) - 1; - return condition <0; - //return (x * x) / (a * a) + (y * y) / (b * b) < 1 + J_EPS_DIST; +bool JEllipse::IsInside(const Point& p) const +{ + double a = GetEA(); + double b = GetEB(); + double x = p.GetX(); + double y = p.GetY(); + double condition = (x * x) / (a * a) + (y * y) / (b * b) - 1; + return condition <0; + //return (x * x) / (a * a) + (y * y) / (b * b) < 1 + J_EPS_DIST; } // check if point given in the ellipse coordinates is outside an ellipse -bool JEllipse::IsOutside(const Point& p) const { - double a = GetEA(); - double b = GetEB(); - double x = p.GetX(); - double y = p.GetY(); - double condition = (x * x) / (a * a) + (y * y) / (b * b) - 1; - return condition >0; - //return (x * x) / (a * a) + (y * y) / (b * b) > 1 - J_EPS_DIST; +bool JEllipse::IsOutside(const Point& p) const +{ + double a = GetEA(); + double b = GetEB(); + double x = p.GetX(); + double y = p.GetY(); + double condition = (x * x) / (a * a) + (y * y) / (b * b) - 1; + return condition >0; + //return (x * x) / (a * a) + (y * y) / (b * b) > 1 - J_EPS_DIST; } // check if point given in the ellipse coordinates is on an ellipse -bool JEllipse::IsOn(const Point& p) const { - double a = GetEA(); - double b = GetEB(); - double x = p.GetX(); - double y = p.GetY(); - double condition = (x * x) / (a * a) + (y * y) / (b * b) - 1; - return (-J_EPS_DIST < condition) && (condition < J_EPS_DIST); - //return (-J_EPS_DIST < impliciteEllipse) && (impliciteEllipse < J_EPS_DIST); +bool JEllipse::IsOn(const Point& p) const +{ + double a = GetEA(); + double b = GetEB(); + double x = p.GetX(); + double y = p.GetY(); + double condition = (x * x) / (a * a) + (y * y) / (b * b) - 1; + return (-J_EPS_DIST < condition) && (condition < J_EPS_DIST); + //return (-J_EPS_DIST < impliciteEllipse) && (impliciteEllipse < J_EPS_DIST); } /*bool Ellipse::IntersectionWithLine(const Line& line) { diff --git a/pedestrian/Ellipse.h b/pedestrian/Ellipse.h index 83947f7008dfbe59292b2086df9d0a8894a80d8a..2b8eaa9dbf7375fca91c5d6db5503759bb26c8e5 100644 --- a/pedestrian/Ellipse.h +++ b/pedestrian/Ellipse.h @@ -34,74 +34,74 @@ #include "../math/Mathematics.h" class JEllipse { - private: - Point _vel; // velocity vector - Point _center; // cartesian-coord of the centre - double _cosPhi; // cos(phi) - double _sinPhi; // sin(phi) - double _Xp; //x Ellipse-coord of the centre (Center in (xc,yc) ) - double _Amin; // pAmin + V * pAv - double _Av; - double _Bmin; // pBmax - V *[(pBmax - pBmin) / V0] - double _Bmax; - double __vel0; // desired speed - - - - public: - - JEllipse(); - JEllipse(const JEllipse& orig); - - - void SetV(const Point& v); - void SetCenter(Point pos); - void SetCosPhi(double c); - void SetSinPhi(double s); - void SetXp(double xp); - void SetAmin(double a_min); - void SetAv(double a_v); - void SetBmin(double b_min); - void SetBmax(double b_max); - void SetV0(double v0); - - - const Point& GetV() const; - const Point& GetCenter() const; - double GetCosPhi() const; - double GetSinPhi() const; - double GetXp() const; - double GetAmin() const; - double GetAv() const; - double GetBmin() const; - double GetBmax() const; - double GetV0() const; - - double GetEA()const;// ellipse semi-axis in the direction of the velocity - double GetEB()const;// ellipse semi-axis in the orthogonal direction of the velocity - double GetArea()const; - - - // Effective distance between two ellipses - double EffectiveDistanceToEllipse(const JEllipse& other, double* dist) const; - // Effective distance between ellipse and line segment - double EffectiveDistanceToLine(const Line& l) const; - // Schnittpunkt der Ellipse mit der Gerade durch P und AP (=ActionPoint von E) - Point PointOnEllipse(const Point& p) const; - // Schnittpunkt der Ellipse mit dem Liniensegment line - Point PointOnEllipse(const Line& line, const Point& P) const; - // minimal möglicher Abstand (durch Verschiebung) Ellipse <-> Segment - //double MinimumDistanceToLine(const Line& l)const; - // minimal möglicher Abstand (durch Verschiebung) Ellipse <-> Ellipse - //double MinimumDistanceToEllipse(const JEllipse& E) const; - // Check if point p is inside the ellipse - bool IsInside(const Point& p) const; - // Check if point p is outside the ellipse - bool IsOutside(const Point& p) const; - // Check if point p is on the ellipse - bool IsOn(const Point& p) const; - - bool IntersectionWithLine(const Line& line); +private: + Point _vel; // velocity vector + Point _center; // cartesian-coord of the centre + double _cosPhi; // cos(phi) + double _sinPhi; // sin(phi) + double _Xp; //x Ellipse-coord of the centre (Center in (xc,yc) ) + double _Amin; // pAmin + V * pAv + double _Av; + double _Bmin; // pBmax - V *[(pBmax - pBmin) / V0] + double _Bmax; + double __vel0; // desired speed + + + +public: + + JEllipse(); + JEllipse(const JEllipse& orig); + + + void SetV(const Point& v); + void SetCenter(Point pos); + void SetCosPhi(double c); + void SetSinPhi(double s); + void SetXp(double xp); + void SetAmin(double a_min); + void SetAv(double a_v); + void SetBmin(double b_min); + void SetBmax(double b_max); + void SetV0(double v0); + + + const Point& GetV() const; + const Point& GetCenter() const; + double GetCosPhi() const; + double GetSinPhi() const; + double GetXp() const; + double GetAmin() const; + double GetAv() const; + double GetBmin() const; + double GetBmax() const; + double GetV0() const; + + double GetEA()const;// ellipse semi-axis in the direction of the velocity + double GetEB()const;// ellipse semi-axis in the orthogonal direction of the velocity + double GetArea()const; + + + // Effective distance between two ellipses + double EffectiveDistanceToEllipse(const JEllipse& other, double* dist) const; + // Effective distance between ellipse and line segment + double EffectiveDistanceToLine(const Line& l) const; + // Schnittpunkt der Ellipse mit der Gerade durch P und AP (=ActionPoint von E) + Point PointOnEllipse(const Point& p) const; + // Schnittpunkt der Ellipse mit dem Liniensegment line + Point PointOnEllipse(const Line& line, const Point& P) const; + // minimal möglicher Abstand (durch Verschiebung) Ellipse <-> Segment + //double MinimumDistanceToLine(const Line& l)const; + // minimal möglicher Abstand (durch Verschiebung) Ellipse <-> Ellipse + //double MinimumDistanceToEllipse(const JEllipse& E) const; + // Check if point p is inside the ellipse + bool IsInside(const Point& p) const; + // Check if point p is outside the ellipse + bool IsOutside(const Point& p) const; + // Check if point p is on the ellipse + bool IsOn(const Point& p) const; + + bool IntersectionWithLine(const Line& line); }; diff --git a/pedestrian/PedDistributor.cpp b/pedestrian/PedDistributor.cpp index 6293f05b85e84d6f8ccdd70d064667911fcbe501..b25f6f02c25d1b1d69f3523c0ca051958028da90 100644 --- a/pedestrian/PedDistributor.cpp +++ b/pedestrian/PedDistributor.cpp @@ -39,124 +39,149 @@ using namespace std; /************************************************************ StartDistributionRoom ************************************************************/ -StartDistributionRoom::StartDistributionRoom() { - _roomID = -1; - _nPeds = -1; - _groupID = -1; - _goalID = -1; - _routerID = -1; - _routeID = -1; - _age = -1; - _height = -1; - _startX = NAN; - _startY = NAN; - _startZ = NAN; - _gender = "male"; +StartDistributionRoom::StartDistributionRoom() +{ + _roomID = -1; + _nPeds = -1; + _groupID = -1; + _goalID = -1; + _routerID = -1; + _routeID = -1; + _age = -1; + _height = -1; + _startX = NAN; + _startY = NAN; + _startZ = NAN; + _gender = "male"; } -StartDistributionRoom::~StartDistributionRoom() { +StartDistributionRoom::~StartDistributionRoom() +{ } -int StartDistributionRoom::GetAgentsNumber() const { - return _nPeds; +int StartDistributionRoom::GetAgentsNumber() const +{ + return _nPeds; } // Setter-Funktionen -void StartDistributionRoom::SetRoomID(int id) { - _roomID = id; +void StartDistributionRoom::SetRoomID(int id) +{ + _roomID = id; } -int StartDistributionRoom::GetAge() const { - return _age; +int StartDistributionRoom::GetAge() const +{ + return _age; } -void StartDistributionRoom::SetAge(int age) { - _age = age; +void StartDistributionRoom::SetAge(int age) +{ + _age = age; } -const std::string& StartDistributionRoom::GetGender() const { - return _gender; +const std::string& StartDistributionRoom::GetGender() const +{ + return _gender; } -void StartDistributionRoom::SetGender(const std::string& gender) { - _gender = gender; +void StartDistributionRoom::SetGender(const std::string& gender) +{ + _gender = gender; } -int StartDistributionRoom::GetGoalId() const { - return _goalID; +int StartDistributionRoom::GetGoalId() const +{ + return _goalID; } -void StartDistributionRoom::SetGoalId(int goalId) { - _goalID = goalId; +void StartDistributionRoom::SetGoalId(int goalId) +{ + _goalID = goalId; } -int StartDistributionRoom::GetGroupId() const { - return _groupID; +int StartDistributionRoom::GetGroupId() const +{ + return _groupID; } -void StartDistributionRoom::SetGroupId(int groupId) { - _groupID = groupId; +void StartDistributionRoom::SetGroupId(int groupId) +{ + _groupID = groupId; } -int StartDistributionRoom::GetHeight() const { - return _height; +int StartDistributionRoom::GetHeight() const +{ + return _height; } -void StartDistributionRoom::SetHeight(int height) { - _height = height; +void StartDistributionRoom::SetHeight(int height) +{ + _height = height; } -int StartDistributionRoom::GetRoomId() const { - return _roomID; +int StartDistributionRoom::GetRoomId() const +{ + return _roomID; } -void StartDistributionRoom::SetRoomId(int roomId) { - _roomID = roomId; +void StartDistributionRoom::SetRoomId(int roomId) +{ + _roomID = roomId; } -int StartDistributionRoom::GetRouteId() const { - return _routeID; +int StartDistributionRoom::GetRouteId() const +{ + return _routeID; } -void StartDistributionRoom::SetRouteId(int routeId) { - _routeID = routeId; +void StartDistributionRoom::SetRouteId(int routeId) +{ + _routeID = routeId; } -int StartDistributionRoom::GetRouterId() const { - return _routerID; +int StartDistributionRoom::GetRouterId() const +{ + return _routerID; } -void StartDistributionRoom::SetRouterId(int routerId) { - _routerID = routerId; +void StartDistributionRoom::SetRouterId(int routerId) +{ + _routerID = routerId; } -void StartDistributionRoom::SetAgentsNumber(int N) { - _nPeds = N; +void StartDistributionRoom::SetAgentsNumber(int N) +{ + _nPeds = N; } /************************************************************ StartDistributionSubRoom ************************************************************/ -StartDistributionSubroom::StartDistributionSubroom() : StartDistributionRoom() { - _subroomID = -1; +StartDistributionSubroom::StartDistributionSubroom() : StartDistributionRoom() +{ + _subroomID = -1; } -StartDistributionSubroom::~StartDistributionSubroom() { +StartDistributionSubroom::~StartDistributionSubroom() +{ } -int StartDistributionSubroom::GetSubroomID() const { - return _subroomID; +int StartDistributionSubroom::GetSubroomID() const +{ + return _subroomID; } // Setter-Funktionen -void StartDistributionSubroom::SetSubroomID(int i) { - _subroomID = i; +void StartDistributionSubroom::SetSubroomID(int i) +{ + _subroomID = i; } @@ -164,474 +189,489 @@ void StartDistributionSubroom::SetSubroomID(int i) { PedDistributor ************************************************************/ -PedDistributor::PedDistributor() { - _v0 = new Equal(1.24, 0.26); - _Bmax = new Equal(0.25, 0.001); - _Bmin = new Equal(0.2, 0.001); - _Atau = new Equal(0.53, 0.001); - _Amin = new Equal(0.18, 0.001); - _Tau = new Equal(0.5, 0.001); +PedDistributor::PedDistributor() +{ + _v0 = new Equal(1.24, 0.26); + _Bmax = new Equal(0.25, 0.001); + _Bmin = new Equal(0.2, 0.001); + _Atau = new Equal(0.53, 0.001); + _Amin = new Equal(0.18, 0.001); + _Tau = new Equal(0.5, 0.001); } PedDistributor::PedDistributor(double v0mu, double v0sigma, double BmaxMu, double BmaxSigma, - double BminMu, double BminSigma, double AtauMu, double AtauSigma, double AminMu, - double AminSigma, double tauMu, double tauSigma) { - _v0 = new Equal(v0mu, v0sigma); - _Bmax = new Equal(BmaxMu, BmaxSigma); - _Bmin = new Equal(BminMu, BminSigma); - _Atau = new Equal(AtauMu, AtauSigma); - _Amin = new Equal(AminMu, AminSigma); - _Tau = new Equal(tauMu, tauSigma); - _start_dis = vector<StartDistributionRoom* > (); - _start_dis_sub = vector<StartDistributionSubroom* > (); + double BminMu, double BminSigma, double AtauMu, double AtauSigma, double AminMu, + double AminSigma, double tauMu, double tauSigma) +{ + _v0 = new Equal(v0mu, v0sigma); + _Bmax = new Equal(BmaxMu, BmaxSigma); + _Bmin = new Equal(BminMu, BminSigma); + _Atau = new Equal(AtauMu, AtauSigma); + _Amin = new Equal(AminMu, AminSigma); + _Tau = new Equal(tauMu, tauSigma); + _start_dis = vector<StartDistributionRoom* > (); + _start_dis_sub = vector<StartDistributionSubroom* > (); } -PedDistributor::~PedDistributor() { - delete _v0; - delete _Bmax; - delete _Bmin; - delete _Atau; - delete _Amin; - delete _Tau; - - for (unsigned int i = 0; i < _start_dis.size(); i++) { - delete _start_dis[i]; - } - for (unsigned int i = 0; i < _start_dis_sub.size(); i++) { - delete _start_dis_sub[i]; - } - _start_dis_sub.clear(); - _start_dis.clear(); -} +PedDistributor::~PedDistributor() +{ + delete _v0; + delete _Bmax; + delete _Bmin; + delete _Atau; + delete _Amin; + delete _Tau; + for (unsigned int i = 0; i < _start_dis.size(); i++) { + delete _start_dis[i]; + } + for (unsigned int i = 0; i < _start_dis_sub.size(); i++) { + delete _start_dis_sub[i]; + } + _start_dis_sub.clear(); + _start_dis.clear(); +} + + +Distribution* PedDistributor::GetV0() const +{ + return _v0; +} -Distribution* PedDistributor::GetV0() const { - return _v0; +Distribution* PedDistributor::GetBmax() const +{ + return _Bmax; } -Distribution* PedDistributor::GetBmax() const { - return _Bmax; +Distribution* PedDistributor::GetBmin() const +{ + return _Bmin; } -Distribution* PedDistributor::GetBmin() const { - return _Bmin; +Distribution* PedDistributor::GetAtau() const +{ + return _Atau; } -Distribution* PedDistributor::GetAtau() const { - return _Atau; +Distribution* PedDistributor::GetAmin() const +{ + return _Amin; } -Distribution* PedDistributor::GetAmin() const { - return _Amin; +Distribution* PedDistributor::GetTau() const +{ + return _Tau; } -Distribution* PedDistributor::GetTau() const { - return _Tau; -} - -void PedDistributor::InitDistributor(const string& filename){ - _projectFilename=filename; - Log->Write("INFO: \tLoading and parsing the persons attributes"); - - TiXmlDocument doc(_projectFilename); - - if (!doc.LoadFile()){ - Log->Write("ERROR: \t%s", doc.ErrorDesc()); - Log->Write("ERROR: \t could not parse the project file"); - exit(EXIT_FAILURE); - } - - - TiXmlNode* xRootNode = doc.RootElement()->FirstChild("agents"); - if( ! xRootNode ) { - Log->Write("ERROR:\tcould not load persons attributes"); - exit(EXIT_FAILURE); - } - - - TiXmlNode* xDist=xRootNode->FirstChild("agents_distribution"); - for(TiXmlElement* e = xDist->FirstChildElement("group"); e; - e = e->NextSiblingElement("group")) { +void PedDistributor::InitDistributor(const string& filename) +{ + _projectFilename=filename; + Log->Write("INFO: \tLoading and parsing the persons attributes"); - int room_id = xmltoi(e->Attribute("room_id")); - int subroom_id = xmltoi(e->Attribute("subroom_id"),-1); - int number = xmltoi(e->Attribute("number"),0); + TiXmlDocument doc(_projectFilename); - int goal_id = xmltoi(e->Attribute("goal_id"), FINAL_DEST_OUT); - int router_id = xmltoi(e->Attribute("router_id"), -1); - int route_id = xmltoi(e->Attribute("route_id"), -1); - int age = xmltoi(e->Attribute("age"), -1); - string gender = xmltoa(e->Attribute("gender"), "male"); - double height = xmltof(e->Attribute("height"), -1); - double patience= xmltof(e->Attribute("patience"), 5); + if (!doc.LoadFile()) { + Log->Write("ERROR: \t%s", doc.ErrorDesc()); + Log->Write("ERROR: \t could not parse the project file"); + exit(EXIT_FAILURE); + } - StartDistributionRoom* dis=NULL; - if(subroom_id==-1){ - dis = new StartDistributionRoom(); - _start_dis.push_back(dis); - }else{ - dis = new StartDistributionSubroom(); - dynamic_cast<StartDistributionSubroom*>(dis)->SetSubroomID(subroom_id); - _start_dis_sub.push_back(dynamic_cast<StartDistributionSubroom*>(dis)); - } - - dis->SetRoomID(room_id); - dis->SetAgentsNumber(number); - dis->SetAge(age); - dis->SetGender(gender); - dis->SetGoalId(goal_id); - dis->SetRouteId(route_id); - dis->SetRouterId(router_id); - dis->SetHeight(height); - dis->SetPatience(patience); - - if(e->Attribute("startX") && e->Attribute("startY")){ - double startX = xmltof(e->Attribute("startX"),NAN); - double startY = xmltof(e->Attribute("startY"),NAN); - //todo: verify that the position is valid (not nan) - dis->SetStartPosition(startX,startY,0.0); - } - } - - //TODO: Parse the sources - TiXmlNode* xSources=xRootNode->FirstChild("agents_sources"); - if(xSources) - for(TiXmlElement* e = xSources->FirstChildElement("source"); e; - e = e->NextSiblingElement("source")) { - Log->Write("INFO:\tSource with id %s will not be parsed !",e->Attribute("id")); - - } - - Log->Write("INFO: \t...Done"); -} - -int PedDistributor::Distribute(Building* building) const { - - Log->Write("INFO: \tInit Distribute"); - - int nPeds = 0; - - //first compute all possible positions in the geometry - vector<vector< vector<Point > > > allFreePos = vector<vector< vector<Point > > >(); - for (int r = 0; r < building->GetNumberOfRooms(); r++) { - vector< vector<Point > > allFreePosRoom = vector< vector<Point > > (); - Room* room = building->GetRoom(r); - if(room->GetCaption()=="outside") continue; - for (int s = 0; s < room->GetNumberOfSubRooms(); s++) { - SubRoom* subr = room->GetSubRoom(s); - allFreePosRoom.push_back(PossiblePositions(subr)); - } - allFreePos.push_back(allFreePosRoom); - } - - // first perform the distribution according to the subrooms (if any) - - int pid = 1; // the pedID is being increased throughout... - for (int i = 0; i < (int) _start_dis_sub.size(); i++) { - - int room_id = _start_dis_sub[i]->GetRoomId(); - Room* r = building->GetRoom(room_id); - if(!r) continue; - - int roomID = r->GetID(); - - int subroomID = _start_dis_sub[i]->GetSubroomID(); - int N = _start_dis_sub[i]->GetAgentsNumber(); - if (N < 0) { - Log->Write("ERROR: \t negative (or null ) number of pedestrians!"); - exit(EXIT_FAILURE); - } - - vector<Point> &allpos = allFreePos[roomID][subroomID]; - int max_pos = allpos.size(); - if (max_pos < N) { - Log->Write("ERROR: \tCannot distribute %d agents in Room %d . Maximum allowed: %d\n", - N, roomID, allpos.size()); - exit(EXIT_FAILURE); - } - - // Distributing - Log->Write("INFO: \tDistributing %d Agents in Room/Subrom [%d/%d]! Maximum allowed: %d", N, roomID, subroomID, max_pos); - SubRoom* sr = building->GetRoom(roomID)->GetSubRoom(subroomID); - DistributeInSubRoom(sr, N, allpos, &pid,_start_dis_sub[i],building); - Log->Write("\t...Done"); - - nPeds += N; - } - - // then continue the distribution according to the rooms - for (int i = 0; i < (int) _start_dis.size(); i++) { - int room_id = _start_dis[i]->GetRoomId(); - Room* r = building->GetRoom(room_id); - if(!r) continue; - int N = _start_dis[i]->GetAgentsNumber(); - if (N < 0) { - Log->Write("ERROR: \t negative number of pedestrians! Ignoring"); - continue; - } - - double sum_area = 0; - int max_pos = 0; - double ppm; // pedestrians per square meter - int ges_anz = 0; - vector<int> max_anz = vector<int>(); - vector<int> akt_anz = vector<int>(); - - vector< vector<Point > >& allFreePosInRoom=allFreePos[room_id]; - for (int is = 0; is < r->GetNumberOfSubRooms(); is++) { - SubRoom* sr = r->GetSubRoom(is); - double area = sr->GetArea(); - sum_area += area; - int anz = allFreePosInRoom[is].size(); - max_anz.push_back(anz); - max_pos += anz; - } - if (max_pos < N) { - Log->Write("ERROR: \t Distribution of %d pedestrians in Room %d not possible! Maximum allowed: %d\n", - N, r->GetID(), max_pos); - exit(0); - } - ppm = N / sum_area; - // Anzahl der Personen pro SubRoom bestimmen - for (int is = 0; is < r->GetNumberOfSubRooms(); is++) { - SubRoom* sr = r->GetSubRoom(is); - int anz = sr->GetArea() * ppm + 0.5; // wird absichtlich gerundet - while (anz > max_anz[is]) { - anz--; - } - akt_anz.push_back(anz); - ges_anz += anz; - } - // Falls N noch nicht ganz erreicht, von vorne jeweils eine Person dazu - int j = 0; - while (ges_anz < N) { - if (akt_anz[j] < max_anz[j]) { - akt_anz[j] = akt_anz[j] + 1; - ges_anz++; - } - j = (j + 1) % max_anz.size(); - } - j = 0; - while (ges_anz > N) { - if (akt_anz[j] > 0) { - akt_anz[j] = akt_anz[j] - 1; - ges_anz--; - } - j = (j + 1) % max_anz.size(); - } - // distributing - for (unsigned int is = 0; is < akt_anz.size(); is++) { - SubRoom* sr = r->GetSubRoom(is); - if (akt_anz[is] > 0) - DistributeInSubRoom(sr, akt_anz[is], allFreePosInRoom[is], &pid, (StartDistributionSubroom*)_start_dis[i],building); - } - nPeds += N; - } - - return nPeds; -} - -bool PedDistributor::FindPedAndDeleteFromRoom(Building* building,Pedestrian*ped) const { - - for (int i = 0; i < building->GetNumberOfRooms(); i++) { - Room* room = building->GetRoom(i); - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - for (int k = 0; k < sub->GetNumberOfPedestrians(); k++) { - Pedestrian* p=sub->GetPedestrian(k); - if(p->GetID()==ped->GetID()){ - sub->DeletePedestrian(k); - return true; - } - } - } - } - return false; + TiXmlNode* xRootNode = doc.RootElement()->FirstChild("agents"); + if( ! xRootNode ) { + Log->Write("ERROR:\tcould not load persons attributes"); + exit(EXIT_FAILURE); + } + + + TiXmlNode* xDist=xRootNode->FirstChild("agents_distribution"); + for(TiXmlElement* e = xDist->FirstChildElement("group"); e; + e = e->NextSiblingElement("group")) { + + int room_id = xmltoi(e->Attribute("room_id")); + int subroom_id = xmltoi(e->Attribute("subroom_id"),-1); + int number = xmltoi(e->Attribute("number"),0); + + int goal_id = xmltoi(e->Attribute("goal_id"), FINAL_DEST_OUT); + int router_id = xmltoi(e->Attribute("router_id"), -1); + int route_id = xmltoi(e->Attribute("route_id"), -1); + int age = xmltoi(e->Attribute("age"), -1); + string gender = xmltoa(e->Attribute("gender"), "male"); + double height = xmltof(e->Attribute("height"), -1); + double patience= xmltof(e->Attribute("patience"), 5); + + StartDistributionRoom* dis=NULL; + + if(subroom_id==-1) { + dis = new StartDistributionRoom(); + _start_dis.push_back(dis); + } else { + dis = new StartDistributionSubroom(); + dynamic_cast<StartDistributionSubroom*>(dis)->SetSubroomID(subroom_id); + _start_dis_sub.push_back(dynamic_cast<StartDistributionSubroom*>(dis)); + } + + dis->SetRoomID(room_id); + dis->SetAgentsNumber(number); + dis->SetAge(age); + dis->SetGender(gender); + dis->SetGoalId(goal_id); + dis->SetRouteId(route_id); + dis->SetRouterId(router_id); + dis->SetHeight(height); + dis->SetPatience(patience); + + if(e->Attribute("startX") && e->Attribute("startY")) { + double startX = xmltof(e->Attribute("startX"),NAN); + double startY = xmltof(e->Attribute("startY"),NAN); + //todo: verify that the position is valid (not nan) + dis->SetStartPosition(startX,startY,0.0); + } + } + + //TODO: Parse the sources + TiXmlNode* xSources=xRootNode->FirstChild("agents_sources"); + if(xSources) + for(TiXmlElement* e = xSources->FirstChildElement("source"); e; + e = e->NextSiblingElement("source")) { + Log->Write("INFO:\tSource with id %s will not be parsed !",e->Attribute("id")); + + } + + Log->Write("INFO: \t...Done"); +} + +int PedDistributor::Distribute(Building* building) const +{ + + Log->Write("INFO: \tInit Distribute"); + + int nPeds = 0; + + //first compute all possible positions in the geometry + vector<vector< vector<Point > > > allFreePos = vector<vector< vector<Point > > >(); + for (int r = 0; r < building->GetNumberOfRooms(); r++) { + vector< vector<Point > > allFreePosRoom = vector< vector<Point > > (); + Room* room = building->GetRoom(r); + if(room->GetCaption()=="outside") continue; + for (int s = 0; s < room->GetNumberOfSubRooms(); s++) { + SubRoom* subr = room->GetSubRoom(s); + allFreePosRoom.push_back(PossiblePositions(subr)); + } + allFreePos.push_back(allFreePosRoom); + } + + // first perform the distribution according to the subrooms (if any) + + int pid = 1; // the pedID is being increased throughout... + for (int i = 0; i < (int) _start_dis_sub.size(); i++) { + + int room_id = _start_dis_sub[i]->GetRoomId(); + Room* r = building->GetRoom(room_id); + if(!r) continue; + + int roomID = r->GetID(); + + int subroomID = _start_dis_sub[i]->GetSubroomID(); + int N = _start_dis_sub[i]->GetAgentsNumber(); + if (N < 0) { + Log->Write("ERROR: \t negative (or null ) number of pedestrians!"); + exit(EXIT_FAILURE); + } + + vector<Point> &allpos = allFreePos[roomID][subroomID]; + int max_pos = allpos.size(); + if (max_pos < N) { + Log->Write("ERROR: \tCannot distribute %d agents in Room %d . Maximum allowed: %d\n", + N, roomID, allpos.size()); + exit(EXIT_FAILURE); + } + + // Distributing + Log->Write("INFO: \tDistributing %d Agents in Room/Subrom [%d/%d]! Maximum allowed: %d", N, roomID, subroomID, max_pos); + SubRoom* sr = building->GetRoom(roomID)->GetSubRoom(subroomID); + DistributeInSubRoom(sr, N, allpos, &pid,_start_dis_sub[i],building); + Log->Write("\t...Done"); + + nPeds += N; + } + + // then continue the distribution according to the rooms + for (int i = 0; i < (int) _start_dis.size(); i++) { + int room_id = _start_dis[i]->GetRoomId(); + Room* r = building->GetRoom(room_id); + if(!r) continue; + int N = _start_dis[i]->GetAgentsNumber(); + if (N < 0) { + Log->Write("ERROR: \t negative number of pedestrians! Ignoring"); + continue; + } + + double sum_area = 0; + int max_pos = 0; + double ppm; // pedestrians per square meter + int ges_anz = 0; + vector<int> max_anz = vector<int>(); + vector<int> akt_anz = vector<int>(); + + vector< vector<Point > >& allFreePosInRoom=allFreePos[room_id]; + for (int is = 0; is < r->GetNumberOfSubRooms(); is++) { + SubRoom* sr = r->GetSubRoom(is); + double area = sr->GetArea(); + sum_area += area; + int anz = allFreePosInRoom[is].size(); + max_anz.push_back(anz); + max_pos += anz; + } + if (max_pos < N) { + Log->Write("ERROR: \t Distribution of %d pedestrians in Room %d not possible! Maximum allowed: %d\n", + N, r->GetID(), max_pos); + exit(0); + } + ppm = N / sum_area; + // Anzahl der Personen pro SubRoom bestimmen + for (int is = 0; is < r->GetNumberOfSubRooms(); is++) { + SubRoom* sr = r->GetSubRoom(is); + int anz = sr->GetArea() * ppm + 0.5; // wird absichtlich gerundet + while (anz > max_anz[is]) { + anz--; + } + akt_anz.push_back(anz); + ges_anz += anz; + } + // Falls N noch nicht ganz erreicht, von vorne jeweils eine Person dazu + int j = 0; + while (ges_anz < N) { + if (akt_anz[j] < max_anz[j]) { + akt_anz[j] = akt_anz[j] + 1; + ges_anz++; + } + j = (j + 1) % max_anz.size(); + } + j = 0; + while (ges_anz > N) { + if (akt_anz[j] > 0) { + akt_anz[j] = akt_anz[j] - 1; + ges_anz--; + } + j = (j + 1) % max_anz.size(); + } + // distributing + for (unsigned int is = 0; is < akt_anz.size(); is++) { + SubRoom* sr = r->GetSubRoom(is); + if (akt_anz[is] > 0) + DistributeInSubRoom(sr, akt_anz[is], allFreePosInRoom[is], &pid, (StartDistributionSubroom*)_start_dis[i],building); + } + nPeds += N; + } + + return nPeds; +} + +bool PedDistributor::FindPedAndDeleteFromRoom(Building* building,Pedestrian*ped) const +{ + + for (int i = 0; i < building->GetNumberOfRooms(); i++) { + Room* room = building->GetRoom(i); + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + for (int k = 0; k < sub->GetNumberOfPedestrians(); k++) { + Pedestrian* p=sub->GetPedestrian(k); + if(p->GetID()==ped->GetID()) { + sub->DeletePedestrian(k); + return true; + } + } + } + } + return false; } vector<Point> PedDistributor::PositionsOnFixX(double min_x, double max_x, double min_y, double max_y, - SubRoom* r, double bufx, double bufy, double dy) const { - vector<Point> positions; - double x = (max_x + min_x)*0.5; - double y = min_y; - - while (y < max_y) { - Point pos = Point(x, y); - // Abstand zu allen Wänden prüfen - int k; - for (k = 0; k < r->GetNumberOfWalls(); k++) { - if (r->GetWall(k).DistTo(pos) < max(bufx, bufy) || !r->IsInSubRoom(pos)) { - break; // Punkt ist zu nah an einer Wand oder nicht im Raum => ungültig - } - } - if (k == r->GetNumberOfWalls()) { - //check all transitions - bool tooNear=false; - for(unsigned int t=0;t<r->GetAllTransitions().size();t++){ - if(r->GetTransition(t)->DistTo(pos)<J_EPS_GOAL){ - //too close - tooNear=true; - break; - } - } - - - for(unsigned int c=0;c<r->GetAllCrossings().size();c++){ - if(r->GetCrossing(c)->DistTo(pos)<J_EPS_GOAL){ - //too close - tooNear=true; - break; - } - } - if(tooNear==false) positions.push_back(pos); - } - y += dy; - } - return positions; + SubRoom* r, double bufx, double bufy, double dy) const +{ + vector<Point> positions; + double x = (max_x + min_x)*0.5; + double y = min_y; + + while (y < max_y) { + Point pos = Point(x, y); + // Abstand zu allen Wänden prüfen + int k; + for (k = 0; k < r->GetNumberOfWalls(); k++) { + if (r->GetWall(k).DistTo(pos) < max(bufx, bufy) || !r->IsInSubRoom(pos)) { + break; // Punkt ist zu nah an einer Wand oder nicht im Raum => ungültig + } + } + if (k == r->GetNumberOfWalls()) { + //check all transitions + bool tooNear=false; + for(unsigned int t=0; t<r->GetAllTransitions().size(); t++) { + if(r->GetTransition(t)->DistTo(pos)<J_EPS_GOAL) { + //too close + tooNear=true; + break; + } + } + + + for(unsigned int c=0; c<r->GetAllCrossings().size(); c++) { + if(r->GetCrossing(c)->DistTo(pos)<J_EPS_GOAL) { + //too close + tooNear=true; + break; + } + } + if(tooNear==false) positions.push_back(pos); + } + y += dy; + } + return positions; } vector<Point>PedDistributor::PositionsOnFixY(double min_x, double max_x, double min_y, double max_y, - SubRoom* r, double bufx, double bufy, double dx) const { - vector<Point> positions; - double y = (max_y + min_y)*0.5; - double x = min_x; - - while (x < max_x) { - Point pos = Point(x, y); - // check distance to wall - int k; - for (k = 0; k < r->GetNumberOfWalls(); k++) { - if (r->GetWall(k).DistTo(pos) < max(bufx, bufy) || !r->IsInSubRoom(pos)) { - break; // Punkt ist zu nah an einer Wand oder nicht im Raum => ungültig - } - } - if (k == r->GetNumberOfWalls()) { - //check all transitions - bool tooNear=false; - for(unsigned int t=0;t<r->GetAllTransitions().size();t++){ - if(r->GetTransition(t)->DistTo(pos)<J_EPS_GOAL){ - //too close - tooNear=true; - break; - } - } - - for(unsigned int c=0;c<r->GetAllCrossings().size();c++){ - if(r->GetCrossing(c)->DistTo(pos)<J_EPS_GOAL){ - //too close - tooNear=true; - break; - } - } - if(tooNear==false) positions.push_back(pos); - } - x += dx; - } - return positions; + SubRoom* r, double bufx, double bufy, double dx) const +{ + vector<Point> positions; + double y = (max_y + min_y)*0.5; + double x = min_x; + + while (x < max_x) { + Point pos = Point(x, y); + // check distance to wall + int k; + for (k = 0; k < r->GetNumberOfWalls(); k++) { + if (r->GetWall(k).DistTo(pos) < max(bufx, bufy) || !r->IsInSubRoom(pos)) { + break; // Punkt ist zu nah an einer Wand oder nicht im Raum => ungültig + } + } + if (k == r->GetNumberOfWalls()) { + //check all transitions + bool tooNear=false; + for(unsigned int t=0; t<r->GetAllTransitions().size(); t++) { + if(r->GetTransition(t)->DistTo(pos)<J_EPS_GOAL) { + //too close + tooNear=true; + break; + } + } + + for(unsigned int c=0; c<r->GetAllCrossings().size(); c++) { + if(r->GetCrossing(c)->DistTo(pos)<J_EPS_GOAL) { + //too close + tooNear=true; + break; + } + } + if(tooNear==false) positions.push_back(pos); + } + x += dx; + } + return positions; } //TODO: this can be speeded up by passing position as reference -vector<Point> PedDistributor::PossiblePositions(SubRoom* r) const { - double uni = 0.7; // wenn ein Raum in x oder y -Richtung schmaler ist als 0.7 wird in der Mitte verteilt - double bufx = 0.12; - double bufy = 0.12; - - double dx = GetAmin()->GetMean() + bufx; - double dy = GetBmax()->GetMean() + bufy; - - vector<double>::iterator min_x, max_x, min_y, max_y; - vector<Point> poly = r->GetPolygon(); - vector<Point> positions; - vector<double> xs; - vector<double> ys; - - for (int p = 0; p < (int) poly.size(); ++p) { - xs.push_back(poly[p].GetX()); - ys.push_back(poly[p].GetY()); - } - - min_x = min_element(xs.begin(), xs.end()); - max_x = max_element(xs.begin(), xs.end()); - min_y = min_element(ys.begin(), ys.end()); - max_y = max_element(ys.begin(), ys.end()); - - if (*max_y - *min_y < uni) { - positions = PositionsOnFixY(*min_x, *max_x, *min_y, *max_y, r, bufx, bufy, dx); - } else if (*max_x - *min_x < uni) { - positions = PositionsOnFixX(*min_x, *max_x, *min_y, *max_y, r, bufx, bufy, dy); - } else { - // create the grid - double x = (*min_x); - while (x < *max_x) { - double y = (*min_y); - while (y < *max_y) { - y += dy; - Point pos = Point(x, y); - bool tooNear=false; - - // check the distance to all Wall - for (int k = 0; k < r->GetNumberOfWalls(); k++) { - const Wall& w = r->GetWall(k); - if (w.DistTo(pos) < max(bufx, bufy) || !r->IsInSubRoom(pos)) { - tooNear=true; - break; // too close - } - } - - //check all transitions - if(tooNear==true) continue; - for(unsigned int t=0;t<r->GetAllTransitions().size();t++){ - if(r->GetTransition(t)->DistTo(pos)<max(bufx, bufy)){ - //too close - tooNear=true; - break; - } - } - - // and check all crossings - if(tooNear==true) continue; - for(unsigned int c=0;c<r->GetAllCrossings().size();c++){ - if(r->GetCrossing(c)->DistTo(pos)<max(bufx, bufy)){ - //too close - tooNear=true; - break; - } - } - - // and finally all opened obstacles - if(tooNear==true) continue; - - const vector<Obstacle*>& obstacles = r->GetAllObstacles(); - for (unsigned int obs = 0; obs < obstacles.size(); ++obs) { - Obstacle *obst =obstacles[obs]; - const vector<Wall>& walls = obst->GetAllWalls(); - for (unsigned int i = 0; i < walls.size(); i++) { - if (walls[i].DistTo(pos) < max(bufx, bufy) || !r->IsInSubRoom(pos)) { - tooNear=true; - break; // too close - } - } - - //only continue if... - if(tooNear==true) continue; - - if((obst->GetClosed()==1) && (obst->Contains(pos)==true)){ - tooNear=true; - break; // too close - } - } - - if(tooNear==false) positions.push_back(pos); - } - x += dx; - } - } - - return positions; +vector<Point> PedDistributor::PossiblePositions(SubRoom* r) const +{ + double uni = 0.7; // wenn ein Raum in x oder y -Richtung schmaler ist als 0.7 wird in der Mitte verteilt + double bufx = 0.12; + double bufy = 0.12; + + double dx = GetAmin()->GetMean() + bufx; + double dy = GetBmax()->GetMean() + bufy; + + vector<double>::iterator min_x, max_x, min_y, max_y; + vector<Point> poly = r->GetPolygon(); + vector<Point> positions; + vector<double> xs; + vector<double> ys; + + for (int p = 0; p < (int) poly.size(); ++p) { + xs.push_back(poly[p].GetX()); + ys.push_back(poly[p].GetY()); + } + + min_x = min_element(xs.begin(), xs.end()); + max_x = max_element(xs.begin(), xs.end()); + min_y = min_element(ys.begin(), ys.end()); + max_y = max_element(ys.begin(), ys.end()); + + if (*max_y - *min_y < uni) { + positions = PositionsOnFixY(*min_x, *max_x, *min_y, *max_y, r, bufx, bufy, dx); + } else if (*max_x - *min_x < uni) { + positions = PositionsOnFixX(*min_x, *max_x, *min_y, *max_y, r, bufx, bufy, dy); + } else { + // create the grid + double x = (*min_x); + while (x < *max_x) { + double y = (*min_y); + while (y < *max_y) { + y += dy; + Point pos = Point(x, y); + bool tooNear=false; + + // check the distance to all Wall + for (int k = 0; k < r->GetNumberOfWalls(); k++) { + const Wall& w = r->GetWall(k); + if (w.DistTo(pos) < max(bufx, bufy) || !r->IsInSubRoom(pos)) { + tooNear=true; + break; // too close + } + } + + //check all transitions + if(tooNear==true) continue; + for(unsigned int t=0; t<r->GetAllTransitions().size(); t++) { + if(r->GetTransition(t)->DistTo(pos)<max(bufx, bufy)) { + //too close + tooNear=true; + break; + } + } + + // and check all crossings + if(tooNear==true) continue; + for(unsigned int c=0; c<r->GetAllCrossings().size(); c++) { + if(r->GetCrossing(c)->DistTo(pos)<max(bufx, bufy)) { + //too close + tooNear=true; + break; + } + } + + // and finally all opened obstacles + if(tooNear==true) continue; + + const vector<Obstacle*>& obstacles = r->GetAllObstacles(); + for (unsigned int obs = 0; obs < obstacles.size(); ++obs) { + Obstacle *obst =obstacles[obs]; + const vector<Wall>& walls = obst->GetAllWalls(); + for (unsigned int i = 0; i < walls.size(); i++) { + if (walls[i].DistTo(pos) < max(bufx, bufy) || !r->IsInSubRoom(pos)) { + tooNear=true; + break; // too close + } + } + + //only continue if... + if(tooNear==true) continue; + + if((obst->GetClosed()==1) && (obst->Contains(pos)==true)) { + tooNear=true; + break; // too close + } + } + + if(tooNear==false) positions.push_back(pos); + } + x += dx; + } + } + + return positions; } /* Verteilt N Fußgänger in SubRoom r * Algorithms: @@ -649,95 +689,101 @@ vector<Point> PedDistributor::PossiblePositions(SubRoom* r) const { * - routing: wird benötigt um die Zielline der Fußgänger zu initialisieren * */ void PedDistributor::DistributeInSubRoom(SubRoom* r,int nAgents , vector<Point>& positions, int* pid, - StartDistributionSubroom* para, Building* building) const { - - // set the pedestrians - for (int i = 0; i < nAgents; ++i) { - - Pedestrian* ped = new Pedestrian(); - // PedIndex - ped->SetID(*pid); - ped->SetAge(para->GetAge()); - ped->SetGender(para->GetGender()); - ped->SetHeight(para->GetHeight()); - ped->SetFinalDestination(para->GetGoalId()); - ped->SetGroup(para->GetGroupId()); - ped->SetRouter(building->GetRoutingEngine()->GetRouter(para->GetRouterId())); - //ped->SetTrip(); //todo: not implemented - - // a und b setzen muss vor v0 gesetzt werden, - // da sonst v0 mit Null überschrieben wird - JEllipse E = JEllipse(); - E.SetAv(GetAtau()->GetRand()); - E.SetAmin(GetAmin()->GetRand()); - E.SetBmax(GetBmax()->GetRand()); - E.SetBmin(GetBmin()->GetRand()); - ped->SetEllipse(E); - ped->SetTau(GetTau()->GetRand()); - ped->SetV0Norm(GetV0()->GetRand()); - // Position - int index = rand() % positions.size(); - Point pos = positions[index]; - ped->SetPos(pos); - ped->SetBuilding(building); - positions.erase(positions.begin() + index); - ped->SetRoomID(para->GetRoomId(),""); - ped->SetSubRoomID(r->GetSubRoomID()); - ped->SetPatienceTime(para->GetPatience()); - - Point start_pos=para->GetStartPosition(); - if((std::isnan(start_pos._x)==0 ) && (std::isnan(start_pos._y)==0 ) ){ - ped->SetPos(start_pos); - Log->Write("INFO: \t fixed position for ped %d in Room %d %s", - pid, para->GetRoomId(), start_pos.toString().c_str()); - } - - r->AddPedestrian(ped); - (*pid)++; - } -} - - -string PedDistributor::writeParameter() const { - string s; - char tmp[CLENGTH]; - - s.append("\tPedestrians Parameter:\n"); - sprintf(tmp, "\t\tv0 ~ N(%f, %f)\n", GetV0()->GetMean(), GetV0()->GetSigma()); - s.append(tmp); - sprintf(tmp, "\t\tb_max ~ N(%f, %f)\n", GetBmax()->GetMean(), GetBmax()->GetSigma()); - s.append(tmp); - sprintf(tmp, "\t\tb_min ~ N(%f, %f)\n", GetBmin()->GetMean(), GetBmin()->GetSigma()); - s.append(tmp); - sprintf(tmp, "\t\ta_min ~ N(%f, %f)\n", GetAmin()->GetMean(), GetAmin()->GetSigma()); - s.append(tmp); - sprintf(tmp, "\t\ta_tau ~ N(%f, %f)\n", GetAtau()->GetMean(), GetAtau()->GetSigma()); - s.append(tmp); - sprintf(tmp, "\t\ttau ~ N(%f, %f)\n", GetTau()->GetMean(), GetTau()->GetSigma()); - s.append(tmp); - - return s; -} - -void StartDistributionRoom::SetStartPosition(double x, double y, double z) { - if(_nPeds!=1){ - Log->Write("INFO:\t you cannot specify the same start position for many agents"); - Log->Write("INFO:\t Ignoring the start position"); - return; - } - _startX=x; - _startY=y; - _startZ=z; -} - -Point StartDistributionRoom::GetStartPosition() const { - return Point(_startX, _startY); -} - -double StartDistributionRoom::GetPatience() const { - return _patience; -} - -void StartDistributionRoom::SetPatience(double patience) { - _patience = patience; + StartDistributionSubroom* para, Building* building) const +{ + + // set the pedestrians + for (int i = 0; i < nAgents; ++i) { + + Pedestrian* ped = new Pedestrian(); + // PedIndex + ped->SetID(*pid); + ped->SetAge(para->GetAge()); + ped->SetGender(para->GetGender()); + ped->SetHeight(para->GetHeight()); + ped->SetFinalDestination(para->GetGoalId()); + ped->SetGroup(para->GetGroupId()); + ped->SetRouter(building->GetRoutingEngine()->GetRouter(para->GetRouterId())); + //ped->SetTrip(); //todo: not implemented + + // a und b setzen muss vor v0 gesetzt werden, + // da sonst v0 mit Null überschrieben wird + JEllipse E = JEllipse(); + E.SetAv(GetAtau()->GetRand()); + E.SetAmin(GetAmin()->GetRand()); + E.SetBmax(GetBmax()->GetRand()); + E.SetBmin(GetBmin()->GetRand()); + ped->SetEllipse(E); + ped->SetTau(GetTau()->GetRand()); + ped->SetV0Norm(GetV0()->GetRand()); + // Position + int index = rand() % positions.size(); + Point pos = positions[index]; + ped->SetPos(pos); + ped->SetBuilding(building); + positions.erase(positions.begin() + index); + ped->SetRoomID(para->GetRoomId(),""); + ped->SetSubRoomID(r->GetSubRoomID()); + ped->SetPatienceTime(para->GetPatience()); + + Point start_pos=para->GetStartPosition(); + if((std::isnan(start_pos._x)==0 ) && (std::isnan(start_pos._y)==0 ) ) { + ped->SetPos(start_pos); + Log->Write("INFO: \t fixed position for ped %d in Room %d %s", + pid, para->GetRoomId(), start_pos.toString().c_str()); + } + + r->AddPedestrian(ped); + (*pid)++; + } +} + + +string PedDistributor::writeParameter() const +{ + string s; + char tmp[CLENGTH]; + + s.append("\tPedestrians Parameter:\n"); + sprintf(tmp, "\t\tv0 ~ N(%f, %f)\n", GetV0()->GetMean(), GetV0()->GetSigma()); + s.append(tmp); + sprintf(tmp, "\t\tb_max ~ N(%f, %f)\n", GetBmax()->GetMean(), GetBmax()->GetSigma()); + s.append(tmp); + sprintf(tmp, "\t\tb_min ~ N(%f, %f)\n", GetBmin()->GetMean(), GetBmin()->GetSigma()); + s.append(tmp); + sprintf(tmp, "\t\ta_min ~ N(%f, %f)\n", GetAmin()->GetMean(), GetAmin()->GetSigma()); + s.append(tmp); + sprintf(tmp, "\t\ta_tau ~ N(%f, %f)\n", GetAtau()->GetMean(), GetAtau()->GetSigma()); + s.append(tmp); + sprintf(tmp, "\t\ttau ~ N(%f, %f)\n", GetTau()->GetMean(), GetTau()->GetSigma()); + s.append(tmp); + + return s; +} + +void StartDistributionRoom::SetStartPosition(double x, double y, double z) +{ + if(_nPeds!=1) { + Log->Write("INFO:\t you cannot specify the same start position for many agents"); + Log->Write("INFO:\t Ignoring the start position"); + return; + } + _startX=x; + _startY=y; + _startZ=z; +} + +Point StartDistributionRoom::GetStartPosition() const +{ + return Point(_startX, _startY); +} + +double StartDistributionRoom::GetPatience() const +{ + return _patience; +} + +void StartDistributionRoom::SetPatience(double patience) +{ + _patience = patience; } diff --git a/pedestrian/PedDistributor.h b/pedestrian/PedDistributor.h index 8b795024fd16af027ea54220de7396cbc1377312..c6dae68de41860013c1152fe83191dc673b44224 100644 --- a/pedestrian/PedDistributor.h +++ b/pedestrian/PedDistributor.h @@ -41,112 +41,112 @@ StartDistributionRoom ************************************************************/ class StartDistributionRoom { - private: - int _roomID; - int _nPeds; - int _groupID; - int _goalID; - int _routerID; - int _routeID; - int _age; - int _height; - double _patience; - //string motivation;// low, normal, high - //int _width; - double _startX; //only valid when _nPeds=1 - double _startY; //only valid when _nPeds=1 - double _startZ; //only valid when _nPeds=1 - - std::string _gender; - - public: - StartDistributionRoom(); - virtual ~StartDistributionRoom(); - - int GetAgentsNumber() const; - - void SetRoomID(int id); - void SetAgentsNumber(int N); - int GetAge() const; - void SetAge(int age); - const std::string& GetGender() const; - void SetGender(const std::string& gender); - int GetGoalId() const; - void SetGoalId(int goalId); - int GetGroupId() const; - void SetGroupId(int groupId); - int GetHeight() const; - void SetHeight(int height); - int GetRoomId() const; - void SetRoomId(int roomId); - int GetRouteId() const; - void SetRouteId(int routeId); - int GetRouterId() const; - void SetRouterId(int routerId); - void SetStartPosition(double x,double y, double z); - Point GetStartPosition() const; - double GetPatience() const; - void SetPatience(double patience); +private: + int _roomID; + int _nPeds; + int _groupID; + int _goalID; + int _routerID; + int _routeID; + int _age; + int _height; + double _patience; + //string motivation;// low, normal, high + //int _width; + double _startX; //only valid when _nPeds=1 + double _startY; //only valid when _nPeds=1 + double _startZ; //only valid when _nPeds=1 + + std::string _gender; + +public: + StartDistributionRoom(); + virtual ~StartDistributionRoom(); + + int GetAgentsNumber() const; + + void SetRoomID(int id); + void SetAgentsNumber(int N); + int GetAge() const; + void SetAge(int age); + const std::string& GetGender() const; + void SetGender(const std::string& gender); + int GetGoalId() const; + void SetGoalId(int goalId); + int GetGroupId() const; + void SetGroupId(int groupId); + int GetHeight() const; + void SetHeight(int height); + int GetRoomId() const; + void SetRoomId(int roomId); + int GetRouteId() const; + void SetRouteId(int routeId); + int GetRouterId() const; + void SetRouterId(int routerId); + void SetStartPosition(double x,double y, double z); + Point GetStartPosition() const; + double GetPatience() const; + void SetPatience(double patience); }; //TODO:FIXME merge the two classes and set the _subRoomID=-1 class StartDistributionSubroom : public StartDistributionRoom { - private: - int _subroomID; +private: + int _subroomID; - public: - StartDistributionSubroom(); - virtual ~StartDistributionSubroom(); +public: + StartDistributionSubroom(); + virtual ~StartDistributionSubroom(); - int GetSubroomID() const; - void SetSubroomID(int i); + int GetSubroomID() const; + void SetSubroomID(int i); }; /************************************************************ PedDistributor ************************************************************/ class PedDistributor { - private: - Distribution* _v0; // Gauss - Verteilung für v0 - Distribution* _Bmax; - Distribution* _Bmin; - Distribution* _Atau; - Distribution* _Amin; - Distribution* _Tau; - std::vector<StartDistributionRoom*> _start_dis; // ID startraum, subroom und Anz - std::vector<StartDistributionSubroom*> _start_dis_sub; // ID startraum, subroom und Anz - std::string _projectFilename; // store the file for later user - - // find aped in a subroom and delete him - bool FindPedAndDeleteFromRoom(Building* building,Pedestrian*ped) const; - - public: - // Konstruktoren - PedDistributor(); - PedDistributor(double v0mu, double v0sigma, double BmaxMu, double BmaxSigma, - double BminMu, double BminSigma, double AtauMu, double AtauSigma, double AminMu, - double AminSigma, double tauMu, double tauSigma); - //PedDistributor(const PedDistributor& orig); - virtual ~PedDistributor(); - // Getter-Funktionen - Distribution* GetV0() const; - Distribution* GetBmax() const; - Distribution* GetBmin() const; - Distribution* GetAtau() const; - Distribution* GetAmin() const; - Distribution* GetTau() const; - - // sonstige Funktionen - std::vector<Point> PositionsOnFixX(double max_x, double min_x, double max_y, double min_y, - SubRoom* r, double bufx, double bufy, double dy) const; - std::vector<Point> PositionsOnFixY(double max_x, double min_x, double max_y, double min_y, - SubRoom* r, double bufx, double bufy, double dx) const; - std::vector<Point> PossiblePositions(SubRoom* r) const; - void DistributeInSubRoom(SubRoom* r, int N, std::vector<Point>& positions, int* pid, StartDistributionSubroom* parameters,Building* building) const; - std::string writeParameter() const; - - void InitDistributor(const std::string &start_file); - int Distribute(Building* building) const; +private: + Distribution* _v0; // Gauss - Verteilung für v0 + Distribution* _Bmax; + Distribution* _Bmin; + Distribution* _Atau; + Distribution* _Amin; + Distribution* _Tau; + std::vector<StartDistributionRoom*> _start_dis; // ID startraum, subroom und Anz + std::vector<StartDistributionSubroom*> _start_dis_sub; // ID startraum, subroom und Anz + std::string _projectFilename; // store the file for later user + + // find aped in a subroom and delete him + bool FindPedAndDeleteFromRoom(Building* building,Pedestrian*ped) const; + +public: + // Konstruktoren + PedDistributor(); + PedDistributor(double v0mu, double v0sigma, double BmaxMu, double BmaxSigma, + double BminMu, double BminSigma, double AtauMu, double AtauSigma, double AminMu, + double AminSigma, double tauMu, double tauSigma); + //PedDistributor(const PedDistributor& orig); + virtual ~PedDistributor(); + // Getter-Funktionen + Distribution* GetV0() const; + Distribution* GetBmax() const; + Distribution* GetBmin() const; + Distribution* GetAtau() const; + Distribution* GetAmin() const; + Distribution* GetTau() const; + + // sonstige Funktionen + std::vector<Point> PositionsOnFixX(double max_x, double min_x, double max_y, double min_y, + SubRoom* r, double bufx, double bufy, double dy) const; + std::vector<Point> PositionsOnFixY(double max_x, double min_x, double max_y, double min_y, + SubRoom* r, double bufx, double bufy, double dx) const; + std::vector<Point> PossiblePositions(SubRoom* r) const; + void DistributeInSubRoom(SubRoom* r, int N, std::vector<Point>& positions, int* pid, StartDistributionSubroom* parameters,Building* building) const; + std::string writeParameter() const; + + void InitDistributor(const std::string &start_file); + int Distribute(Building* building) const; }; #endif /* _PEDDISTRIBUTOR_H */ diff --git a/pedestrian/Pedestrian.cpp b/pedestrian/Pedestrian.cpp index 284c397ff0a1624e5731fb142feb798fa68cf22e..7f8d39ca4292c3c675c497c4306e296e4922ff43 100644 --- a/pedestrian/Pedestrian.cpp +++ b/pedestrian/Pedestrian.cpp @@ -40,639 +40,717 @@ bool Pedestrian::_enableSpotlight=false; -Pedestrian::Pedestrian() { - _roomID = -1; - _subRoomID = -1; - _oldRoomID = -1; - _oldSubRoomID = -1; - _exitIndex = -1; - _id = 0; - _mass = 1; - _tau = 0.5; - _newOrientationFlag = false; - _newOrientationDelay = 0; //0 seconds, in steps - _tmpFirstOrientation = true; - _updateRate = 0; - _turninAngle=0.0; - _ellipse = JEllipse(); - _navLine = new NavLine(); //FIXME this is not released - _router=NULL; - _building=NULL; - _reroutingThreshold=0.0; // new orientation after 10 seconds, value is incremented - _timeBeforeRerouting=0.0; - _reroutingEnabled=false; - _timeInJam=0.0; - _patienceTime=5.0;// time after which the ped feels to be in jam - _desiredFinalDestination=FINAL_DEST_OUT; - _mentalMap=map<int, int>(); - _destHistory=vector<int>(); - _deltaT=0.01; - _V0=Point(0,0); - _lastPosition=Point(0,0); - _lastCellPosition=-1; - _recordingTime=5; //seconds - - _knownDoors = map<int, NavLineState>(); - - _height=160; - _age=30; - _gender="male"; - _trip=vector<int> (); - _group=-1; - _spotlight=false; -} - - -Pedestrian::~Pedestrian() { - if(_navLine) delete _navLine; +Pedestrian::Pedestrian() +{ + _roomID = -1; + _subRoomID = -1; + _oldRoomID = -1; + _oldSubRoomID = -1; + _exitIndex = -1; + _id = 0; + _mass = 1; + _tau = 0.5; + _newOrientationFlag = false; + _newOrientationDelay = 0; //0 seconds, in steps + _tmpFirstOrientation = true; + _updateRate = 0; + _turninAngle=0.0; + _ellipse = JEllipse(); + _navLine = new NavLine(); //FIXME this is not released + _router=NULL; + _building=NULL; + _reroutingThreshold=0.0; // new orientation after 10 seconds, value is incremented + _timeBeforeRerouting=0.0; + _reroutingEnabled=false; + _timeInJam=0.0; + _patienceTime=5.0;// time after which the ped feels to be in jam + _desiredFinalDestination=FINAL_DEST_OUT; + _mentalMap=map<int, int>(); + _destHistory=vector<int>(); + _deltaT=0.01; + _V0=Point(0,0); + _lastPosition=Point(0,0); + _lastCellPosition=-1; + _recordingTime=5; //seconds + + _knownDoors = map<int, NavLineState>(); + + _height=160; + _age=30; + _gender="male"; + _trip=vector<int> (); + _group=-1; + _spotlight=false; +} + + +Pedestrian::~Pedestrian() +{ + if(_navLine) delete _navLine; } -void Pedestrian::SetID(int i) { - _id = i; +void Pedestrian::SetID(int i) +{ + _id = i; } -void Pedestrian::SetRoomID(int i, string roomCaption) { - _roomID = i; - _roomCaption=roomCaption; +void Pedestrian::SetRoomID(int i, string roomCaption) +{ + _roomID = i; + _roomCaption=roomCaption; } -void Pedestrian::SetSubRoomID(int i) { - _subRoomID = i; +void Pedestrian::SetSubRoomID(int i) +{ + _subRoomID = i; } -void Pedestrian::SetMass(double m) { - _mass = m; +void Pedestrian::SetMass(double m) +{ + _mass = m; } -void Pedestrian::SetTau(double tau) { - _tau = tau; +void Pedestrian::SetTau(double tau) +{ + _tau = tau; } -void Pedestrian::SetEllipse(const JEllipse& e) { - _ellipse = e; +void Pedestrian::SetEllipse(const JEllipse& e) +{ + _ellipse = e; } -void Pedestrian::SetExitIndex(int i) { - _exitIndex = i; - //save that destination for that room - _mentalMap[GetUniqueRoomID()] = i; - _destHistory.push_back(i); +void Pedestrian::SetExitIndex(int i) +{ + _exitIndex = i; + //save that destination for that room + _mentalMap[GetUniqueRoomID()] = i; + _destHistory.push_back(i); } -void Pedestrian::SetExitLine(const NavLine* l) { - //_navLine = l; - _navLine->SetPoint1(l->GetPoint1()); - _navLine->SetPoint2(l->GetPoint2()); +void Pedestrian::SetExitLine(const NavLine* l) +{ + //_navLine = l; + _navLine->SetPoint1(l->GetPoint1()); + _navLine->SetPoint2(l->GetPoint2()); } -void Pedestrian::SetPos(const Point& pos) { - _ellipse.SetCenter(pos); +void Pedestrian::SetPos(const Point& pos) +{ + _ellipse.SetCenter(pos); - //save the last values for the records - _lastPositions.push(pos); - unsigned int max_size= _recordingTime/_deltaT; - if(_lastPositions.size()> max_size) - _lastPositions.pop(); + //save the last values for the records + _lastPositions.push(pos); + unsigned int max_size= _recordingTime/_deltaT; + if(_lastPositions.size()> max_size) + _lastPositions.pop(); } -void Pedestrian::SetCellPos(int cp){ - _lastCellPosition=cp; +void Pedestrian::SetCellPos(int cp) +{ + _lastCellPosition=cp; } -void Pedestrian::SetV(const Point& v) { - _ellipse.SetV(v); +void Pedestrian::SetV(const Point& v) +{ + _ellipse.SetV(v); - //save the last values for the records - _lastVelocites.push(v); - unsigned int max_size= _recordingTime/_deltaT; - if(_lastVelocites.size()> max_size) - _lastVelocites.pop(); + //save the last values for the records + _lastVelocites.push(v); + unsigned int max_size= _recordingTime/_deltaT; + if(_lastVelocites.size()> max_size) + _lastVelocites.pop(); } -void Pedestrian::SetV0Norm(double v0) { - _ellipse.SetV0(v0); +void Pedestrian::SetV0Norm(double v0) +{ + _ellipse.SetV0(v0); } -void Pedestrian::Setdt(double dt) { - _deltaT = dt; +void Pedestrian::Setdt(double dt) +{ + _deltaT = dt; } -double Pedestrian::Getdt() { - return _deltaT; +double Pedestrian::Getdt() +{ + return _deltaT; } -void Pedestrian::SetTrip(const vector<int>& trip){ - _trip=trip; +void Pedestrian::SetTrip(const vector<int>& trip) +{ + _trip=trip; } -int Pedestrian::GetID() const { - return _id; +int Pedestrian::GetID() const +{ + return _id; } -int Pedestrian::GetRoomID() const { - return _roomID; +int Pedestrian::GetRoomID() const +{ + return _roomID; } -int Pedestrian::GetSubRoomID() const { - return _subRoomID; +int Pedestrian::GetSubRoomID() const +{ + return _subRoomID; } -double Pedestrian::GetMass() const { - return _mass; +double Pedestrian::GetMass() const +{ + return _mass; } -double Pedestrian::GetTau() const { - return _tau; +double Pedestrian::GetTau() const +{ + return _tau; } -const JEllipse& Pedestrian::GetEllipse() const { - return _ellipse; +const JEllipse& Pedestrian::GetEllipse() const +{ + return _ellipse; } -int Pedestrian::GetExitIndex() const { - return _exitIndex; +int Pedestrian::GetExitIndex() const +{ + return _exitIndex; } -NavLine* Pedestrian::GetExitLine() const { - return _navLine; +NavLine* Pedestrian::GetExitLine() const +{ + return _navLine; } -const vector<int>& Pedestrian::GetTrip() const{ - return _trip; +const vector<int>& Pedestrian::GetTrip() const +{ + return _trip; } // return the unique subroom Identifier -int Pedestrian::GetUniqueRoomID() const { - return _roomID * 1000 + _subRoomID; +int Pedestrian::GetUniqueRoomID() const +{ + return _roomID * 1000 + _subRoomID; } // returns the exit Id corresponding to the // unique subroom identifier -int Pedestrian::GetNextDestination() { - if (_mentalMap.count(GetUniqueRoomID()) == 0) { - return -1; - } else { - return _mentalMap[GetUniqueRoomID()]; - } +int Pedestrian::GetNextDestination() +{ + if (_mentalMap.count(GetUniqueRoomID()) == 0) { + return -1; + } else { + return _mentalMap[GetUniqueRoomID()]; + } } -int Pedestrian::GetLastDestination() { - if(_destHistory.size() == 0) - return -1; - else - return _destHistory.back(); +int Pedestrian::GetLastDestination() +{ + if(_destHistory.size() == 0) + return -1; + else + return _destHistory.back(); } -bool Pedestrian::ChangedSubRoom() { - if(_oldRoomID != GetRoomID() || _oldSubRoomID != GetSubRoomID()) { - _oldRoomID = GetRoomID(); - _oldSubRoomID = GetSubRoomID(); - return true; - } - return false; +bool Pedestrian::ChangedSubRoom() +{ + if(_oldRoomID != GetRoomID() || _oldSubRoomID != GetSubRoomID()) { + _oldRoomID = GetRoomID(); + _oldSubRoomID = GetSubRoomID(); + return true; + } + return false; } -int Pedestrian::GetDestinationCount() { - return _destHistory.size(); +int Pedestrian::GetDestinationCount() +{ + return _destHistory.size(); } // erase the peds memory -void Pedestrian::ClearMentalMap(){ - _mentalMap.clear(); - _exitIndex=-1; +void Pedestrian::ClearMentalMap() +{ + _mentalMap.clear(); + _exitIndex=-1; } void Pedestrian::AddKnownClosedDoor(int door) { - if(_knownDoors.find(door) == _knownDoors.end()) { - _knownDoors[door].close(GetGlobalTime()); - } - return; + if(_knownDoors.find(door) == _knownDoors.end()) { + _knownDoors[door].close(GetGlobalTime()); + } + return; } int Pedestrian::DoorKnowledgeCount() const { - return _knownDoors.size(); + return _knownDoors.size(); } set<int> Pedestrian::GetKnownClosedDoors() { - map<int, NavLineState>::iterator it; - set<int> doors_closed; - for(it = _knownDoors.begin(); it != _knownDoors.end(); it++){ + map<int, NavLineState>::iterator it; + set<int> doors_closed; + for(it = _knownDoors.begin(); it != _knownDoors.end(); it++) { - if(it->second.closed()) { - doors_closed.insert(it->first); - } - } + if(it->second.closed()) { + doors_closed.insert(it->first); + } + } - return doors_closed; + return doors_closed; } map<int, NavLineState> * Pedestrian::GetKnownDoors() { - return & _knownDoors; + return & _knownDoors; } void Pedestrian::MergeKnownClosedDoors( map<int, NavLineState> * input) { - map<int, NavLineState>::iterator it; - for(it = input->begin(); it != input->end(); it++) { - //it->second.print(); - if(it->second.isShareable(GetGlobalTime())) { - if(_knownDoors.find(it->first) == _knownDoors.end()) { - _knownDoors[it->first] = NavLineState(); - if(!_knownDoors[it->first].mergeDoor(it->second, GetGlobalTime())) { - _knownDoors.erase(it->first); - } - } else { - _knownDoors[it->first].mergeDoor(it->second, GetGlobalTime()); - } - } - } - return; -} - - - -const Point& Pedestrian::GetPos() const { - return _ellipse.GetCenter(); + map<int, NavLineState>::iterator it; + for(it = input->begin(); it != input->end(); it++) { + //it->second.print(); + if(it->second.isShareable(GetGlobalTime())) { + if(_knownDoors.find(it->first) == _knownDoors.end()) { + _knownDoors[it->first] = NavLineState(); + if(!_knownDoors[it->first].mergeDoor(it->second, GetGlobalTime())) { + _knownDoors.erase(it->first); + } + } else { + _knownDoors[it->first].mergeDoor(it->second, GetGlobalTime()); + } + } + } + return; +} + + + +const Point& Pedestrian::GetPos() const +{ + return _ellipse.GetCenter(); } -int Pedestrian::GetCellPos() const { - return _lastCellPosition; +int Pedestrian::GetCellPos() const +{ + return _lastCellPosition; } -const Point& Pedestrian::GetV() const { - return _ellipse.GetV(); +const Point& Pedestrian::GetV() const +{ + return _ellipse.GetV(); } -const Point& Pedestrian::GetV0() const { - return _V0; +const Point& Pedestrian::GetV0() const +{ + return _V0; } -double Pedestrian::GetV0Norm() const { - return _ellipse.GetV0()*_building->GetRoom(_roomID)->GetSubRoom(_subRoomID)->GetCosAngleWithHorizontal(); +double Pedestrian::GetV0Norm() const +{ + return _ellipse.GetV0()*_building->GetRoom(_roomID)->GetSubRoom(_subRoomID)->GetCosAngleWithHorizontal(); } //get axis in the walking direction -double Pedestrian::GetLargerAxis() const { - return _ellipse.GetEA(); +double Pedestrian::GetLargerAxis() const +{ + return _ellipse.GetEA(); } //get axis in the shoulder direction = orthogonal to the walking direction -double Pedestrian::GetSmallerAxis() const { - return _ellipse.GetEB(); -} - -void Pedestrian::SetPhiPed() { - double cosPhi, sinPhi; - double vx = GetV().GetX(); - double vy = GetV().GetY(); - - if (fabs(vx) > J_EPS || fabs(vy) > J_EPS) - { - double normv = sqrt(vx * vx + vy * vy); //MC, 24.10.12 - cosPhi = vx / normv; - sinPhi = vy / normv; - } - else - { - cosPhi = GetEllipse().GetCosPhi(); - sinPhi = GetEllipse().GetSinPhi(); - } - _ellipse.SetCosPhi(cosPhi); - _ellipse.SetSinPhi(sinPhi); -} - -const Point& Pedestrian::GetV0(const Point& target) { - - const Point& pos = GetPos(); - Point delta = target - pos; - Point new_v0; - - - new_v0 = delta.Normalized(); - _V0 = new_v0; - //printf("MC: delta = [%.2f %.2f]\n", delta.GetX(), delta.GetY()); - //printf("MC: new_V0 = [%.2f %.2f]\n", new_v0.GetX(), new_v0.GetY()); - return _V0; - // aktivieren, wenn Rotation aus sein soll - //pV0 = new_v0; - //return pV0; - - // Rotation - double smoothingGrad = 15; - if (_newOrientationFlag) { - double pi = 3.14159265; - _turninAngle = atan2(new_v0.GetY(), new_v0.GetX()) - atan2(_V0.GetY(), _V0.GetX()); - - // prefer turning of -30° instead of 330° - if (_turninAngle <= -pi)_turninAngle += 2 * pi; - if (_turninAngle >= pi)_turninAngle -= 2 * pi; - - _newOrientationFlag = false; //disable and set the delay - if (fabs(_turninAngle) > 1.22) {// only for turn greater than +/-70 degrees - _newOrientationDelay = 2.0 / _deltaT; //2 seconds/dt, in steps - _updateRate = _newOrientationDelay / smoothingGrad; - } - } - if (_newOrientationDelay > 0) { - double smoothingAngle_k = _turninAngle / smoothingGrad; - if (_newOrientationDelay % _updateRate == 0) { - _V0 = _V0.Rotate(cos(smoothingAngle_k), sin(smoothingAngle_k)); - } - _newOrientationDelay--; - - //stop the rotation if the velocity is too high, 0.9m/s - // this avoid drifting - if (GetV().Norm() > 0.90) { - _newOrientationDelay = 0; - } - } - if (_newOrientationDelay <= 0) { - _V0 = new_v0; - } - - return _V0; -} - -double Pedestrian::GetTimeInJam() const { - return _timeInJam; +double Pedestrian::GetSmallerAxis() const +{ + return _ellipse.GetEB(); +} + +void Pedestrian::SetPhiPed() +{ + double cosPhi, sinPhi; + double vx = GetV().GetX(); + double vy = GetV().GetY(); + + if (fabs(vx) > J_EPS || fabs(vy) > J_EPS) { + double normv = sqrt(vx * vx + vy * vy); //MC, 24.10.12 + cosPhi = vx / normv; + sinPhi = vy / normv; + } else { + cosPhi = GetEllipse().GetCosPhi(); + sinPhi = GetEllipse().GetSinPhi(); + } + _ellipse.SetCosPhi(cosPhi); + _ellipse.SetSinPhi(sinPhi); +} + +const Point& Pedestrian::GetV0(const Point& target) +{ + + const Point& pos = GetPos(); + Point delta = target - pos; + Point new_v0; + + + new_v0 = delta.Normalized(); + _V0 = new_v0; + //printf("MC: delta = [%.2f %.2f]\n", delta.GetX(), delta.GetY()); + //printf("MC: new_V0 = [%.2f %.2f]\n", new_v0.GetX(), new_v0.GetY()); + return _V0; + // aktivieren, wenn Rotation aus sein soll + //pV0 = new_v0; + //return pV0; + + // Rotation + double smoothingGrad = 15; + if (_newOrientationFlag) { + double pi = 3.14159265; + _turninAngle = atan2(new_v0.GetY(), new_v0.GetX()) - atan2(_V0.GetY(), _V0.GetX()); + + // prefer turning of -30° instead of 330° + if (_turninAngle <= -pi)_turninAngle += 2 * pi; + if (_turninAngle >= pi)_turninAngle -= 2 * pi; + + _newOrientationFlag = false; //disable and set the delay + if (fabs(_turninAngle) > 1.22) {// only for turn greater than +/-70 degrees + _newOrientationDelay = 2.0 / _deltaT; //2 seconds/dt, in steps + _updateRate = _newOrientationDelay / smoothingGrad; + } + } + if (_newOrientationDelay > 0) { + double smoothingAngle_k = _turninAngle / smoothingGrad; + if (_newOrientationDelay % _updateRate == 0) { + _V0 = _V0.Rotate(cos(smoothingAngle_k), sin(smoothingAngle_k)); + } + _newOrientationDelay--; + + //stop the rotation if the velocity is too high, 0.9m/s + // this avoid drifting + if (GetV().Norm() > 0.90) { + _newOrientationDelay = 0; + } + } + if (_newOrientationDelay <= 0) { + _V0 = new_v0; + } + + return _V0; +} + +double Pedestrian::GetTimeInJam() const +{ + return _timeInJam; } // set the new orientation flag // to delay sharp turn // TODO: maybe combine this with SetExitLine -void Pedestrian::SetSmoothTurning(bool smt) { - //ignoring first turn - if (_tmpFirstOrientation) { - _tmpFirstOrientation = false; - } else { - if (_newOrientationDelay <= 0)// in the case the pedestrian is still rotating - _newOrientationFlag = smt; - } +void Pedestrian::SetSmoothTurning(bool smt) +{ + //ignoring first turn + if (_tmpFirstOrientation) { + _tmpFirstOrientation = false; + } else { + if (_newOrientationDelay <= 0)// in the case the pedestrian is still rotating + _newOrientationFlag = smt; + } } -bool Pedestrian::IsFeelingLikeInJam(){ - //return true; - return (_patienceTime<_timeInJam); +bool Pedestrian::IsFeelingLikeInJam() +{ + //return true; + return (_patienceTime<_timeInJam); } -void Pedestrian::ResetTimeInJam(){ - _timeInJam=0.0; +void Pedestrian::ResetTimeInJam() +{ + _timeInJam=0.0; } -void Pedestrian::UpdateTimeInJam(){ - _timeInJam+=_deltaT; +void Pedestrian::UpdateTimeInJam() +{ + _timeInJam+=_deltaT; } //TODO: magic -void Pedestrian::UpdateJamData(){ - if(GetV().NormSquare()<0.25*GetV0().NormSquare()){ - _timeInJam+=_deltaT; - }else{ - _timeInJam/=2.0; - } +void Pedestrian::UpdateJamData() +{ + if(GetV().NormSquare()<0.25*GetV0().NormSquare()) { + _timeInJam+=_deltaT; + } else { + _timeInJam/=2.0; + } } -void Pedestrian::UpdateReroutingTime(){ - _timeBeforeRerouting-=_deltaT; +void Pedestrian::UpdateReroutingTime() +{ + _timeBeforeRerouting-=_deltaT; } -void Pedestrian::RerouteIn(double time){ - _reroutingEnabled=true; - _timeBeforeRerouting=time; +void Pedestrian::RerouteIn(double time) +{ + _reroutingEnabled=true; + _timeBeforeRerouting=time; } -bool Pedestrian::IsReadyForRerouting(){ - return(_reroutingEnabled &&(_timeBeforeRerouting<=0.0)); +bool Pedestrian::IsReadyForRerouting() +{ + return(_reroutingEnabled &&(_timeBeforeRerouting<=0.0)); } -double Pedestrian::GetAge() const { - return _age; +double Pedestrian::GetAge() const +{ + return _age; } -void Pedestrian::SetAge(double age) { - _age = age; +void Pedestrian::SetAge(double age) +{ + _age = age; } -string Pedestrian::GetGender() const { - return _gender; +string Pedestrian::GetGender() const +{ + return _gender; } -void Pedestrian::SetGender(string gender) { - _gender = gender; +void Pedestrian::SetGender(string gender) +{ + _gender = gender; } -double Pedestrian::GetHeight() const { - return _height; +double Pedestrian::GetHeight() const +{ + return _height; } -int Pedestrian::GetGroup() const { - return _group; +int Pedestrian::GetGroup() const +{ + return _group; } -void Pedestrian::SetGroup(int group) { - _group = group; +void Pedestrian::SetGroup(int group) +{ + _group = group; } -void Pedestrian::SetHeight(double height) { - _height = height; +void Pedestrian::SetHeight(double height) +{ + _height = height; } -void Pedestrian::ResetRerouting(){ - _reroutingEnabled=false; - _timeBeforeRerouting=-1.00; +void Pedestrian::ResetRerouting() +{ + _reroutingEnabled=false; + _timeBeforeRerouting=-1.00; } -void Pedestrian::SetRecordingTime(double timeInSec){ - _recordingTime=timeInSec; +void Pedestrian::SetRecordingTime(double timeInSec) +{ + _recordingTime=timeInSec; } -double Pedestrian::GetRecordingTime() const{ - return _recordingTime; +double Pedestrian::GetRecordingTime() const +{ + return _recordingTime; } -double Pedestrian::GetAverageVelecityOverRecordingTime() const { - //just few position were saved - if (_lastPositions.size()<2) return _ellipse.GetV().Norm(); - return fabs ( (_lastPositions.back()-_lastPositions.front()).Norm() / _recordingTime ); +double Pedestrian::GetAverageVelecityOverRecordingTime() const +{ + //just few position were saved + if (_lastPositions.size()<2) return _ellipse.GetV().Norm(); + return fabs ( (_lastPositions.back()-_lastPositions.front()).Norm() / _recordingTime ); } -double Pedestrian::GetDistanceToNextTarget() const { - return (_navLine->DistTo(GetPos())); +double Pedestrian::GetDistanceToNextTarget() const +{ + return (_navLine->DistTo(GetPos())); } -void Pedestrian::SetFinalDestination(int final) { - _desiredFinalDestination = final; +void Pedestrian::SetFinalDestination(int final) +{ + _desiredFinalDestination = final; } -int Pedestrian::GetFinalDestination() const { - return _desiredFinalDestination; +int Pedestrian::GetFinalDestination() const +{ + return _desiredFinalDestination; } ///@deprecated -void Pedestrian::WritePath(ofstream& file, Building* building){ - map<int, int>::iterator iter; - - if(building){ - for (iter = _mentalMap.begin(); iter != _mentalMap.end(); iter++) { - file<<building->GetAllRooms()[iter->first/1000]->GetCaption()<<" "<<iter->second<<endl; - } - }else{ - for (iter = _mentalMap.begin(); iter != _mentalMap.end(); iter++) { - file<<iter->first/1000<<" "<<iter->second<<endl; - } - } -} - -string Pedestrian::GetPath(){ - map<int, int>::iterator iter; - string path; +void Pedestrian::WritePath(ofstream& file, Building* building) +{ + map<int, int>::iterator iter; - for (iter = _mentalMap.begin(); iter != _mentalMap.end(); iter++) { - stringstream ss;//create a stringstream - ss << iter->first/1000<<":"<<iter->second<<">"; - path.append(ss.str()); - } - return path; + if(building) { + for (iter = _mentalMap.begin(); iter != _mentalMap.end(); iter++) { + file<<building->GetAllRooms()[iter->first/1000]->GetCaption()<<" "<<iter->second<<endl; + } + } else { + for (iter = _mentalMap.begin(); iter != _mentalMap.end(); iter++) { + file<<iter->first/1000<<" "<<iter->second<<endl; + } + } } -void Pedestrian::Dump(int ID, int pa) { - - if (ID != _id) return; - - printf("------> ped %d <-------\n", _id); - - switch (pa) { - - case 0: - { - printf(">> Room/Subroom [%d / %d]\n", _roomID, _subRoomID); - printf(">> Destination [ %d ]\n", _exitIndex); - printf(">> Final Destination [ %d ]\n", _desiredFinalDestination); - printf(">> Position [%f, %f]\n", GetPos().GetX(), GetPos().GetY()); - printf(">> V0 [%f, %f] Norm = [%f]\n", _V0.GetX(), _V0.GetY(), GetV0Norm()); - printf(">> Velocity [%f, %f] Norm = [%f]\n", GetV().GetX(), GetV().GetY(), GetV().Norm()); - if(GetExitLine()){ - printf(">> ExitLine: (%f, %f) -- (%f, %f)\n", GetExitLine()->GetPoint1().GetX(), GetExitLine()->GetPoint1().GetY(), - GetExitLine()->GetPoint2().GetX(), GetExitLine()->GetPoint2().GetY()); - printf(">> dist: %f\n", GetExitLine()->DistTo(GetPos())); - } - printf(">> smooth rotating: %s \n", (_newOrientationDelay > 0) ? "yes" : "no"); - printf(">> mental map"); - map<int, int>::iterator iter; - for (iter = _mentalMap.begin(); iter != _mentalMap.end(); iter++) { - printf("\t room / destination [%d, %d]\n", iter->first, iter->second); - } - } - break; - - case 1: - printf(">> Position [%f, %f]\n", GetPos().GetX(), GetPos().GetY()); - break; - - case 2: - printf(">> Velocity [%f, %f]\n", GetV().GetX(), GetV().GetY()); - break; - - case 3: - printf(">> V0 [%f, %f] Norm = [%f]\n", _V0.GetX(), _V0.GetY(), GetV0Norm()); - break; - - case 4: - printf(">> Room/Subroom [%d / %d]\n", _roomID, _subRoomID); - break; - - case 5: - printf(">> Destination [ %d ]\n", _exitIndex); - break; - case 6: //Mental Map - { - printf(">> mental map"); - map<int, int>::iterator iter; - for (iter = _mentalMap.begin(); iter != _mentalMap.end(); iter++) { - printf("\t room / destination [%d, %d]", iter->first, iter->second); - } - } - break; +string Pedestrian::GetPath() +{ + map<int, int>::iterator iter; + string path; - } - fflush(stdout); - getc(stdin); + for (iter = _mentalMap.begin(); iter != _mentalMap.end(); iter++) { + stringstream ss;//create a stringstream + ss << iter->first/1000<<":"<<iter->second<<">"; + path.append(ss.str()); + } + return path; } -void Pedestrian::RecordActualPosition(){ - _lastPosition=GetPos(); +void Pedestrian::Dump(int ID, int pa) +{ + + if (ID != _id) return; + + printf("------> ped %d <-------\n", _id); + + switch (pa) { + + case 0: { + printf(">> Room/Subroom [%d / %d]\n", _roomID, _subRoomID); + printf(">> Destination [ %d ]\n", _exitIndex); + printf(">> Final Destination [ %d ]\n", _desiredFinalDestination); + printf(">> Position [%f, %f]\n", GetPos().GetX(), GetPos().GetY()); + printf(">> V0 [%f, %f] Norm = [%f]\n", _V0.GetX(), _V0.GetY(), GetV0Norm()); + printf(">> Velocity [%f, %f] Norm = [%f]\n", GetV().GetX(), GetV().GetY(), GetV().Norm()); + if(GetExitLine()) { + printf(">> ExitLine: (%f, %f) -- (%f, %f)\n", GetExitLine()->GetPoint1().GetX(), GetExitLine()->GetPoint1().GetY(), + GetExitLine()->GetPoint2().GetX(), GetExitLine()->GetPoint2().GetY()); + printf(">> dist: %f\n", GetExitLine()->DistTo(GetPos())); + } + printf(">> smooth rotating: %s \n", (_newOrientationDelay > 0) ? "yes" : "no"); + printf(">> mental map"); + map<int, int>::iterator iter; + for (iter = _mentalMap.begin(); iter != _mentalMap.end(); iter++) { + printf("\t room / destination [%d, %d]\n", iter->first, iter->second); + } + } + break; + + case 1: + printf(">> Position [%f, %f]\n", GetPos().GetX(), GetPos().GetY()); + break; + + case 2: + printf(">> Velocity [%f, %f]\n", GetV().GetX(), GetV().GetY()); + break; + + case 3: + printf(">> V0 [%f, %f] Norm = [%f]\n", _V0.GetX(), _V0.GetY(), GetV0Norm()); + break; + + case 4: + printf(">> Room/Subroom [%d / %d]\n", _roomID, _subRoomID); + break; + + case 5: + printf(">> Destination [ %d ]\n", _exitIndex); + break; + case 6: { //Mental Map + printf(">> mental map"); + map<int, int>::iterator iter; + for (iter = _mentalMap.begin(); iter != _mentalMap.end(); iter++) { + printf("\t room / destination [%d, %d]", iter->first, iter->second); + } + } + break; + + } + fflush(stdout); + getc(stdin); +} + +void Pedestrian::RecordActualPosition() +{ + _lastPosition=GetPos(); } -double Pedestrian::GetDistanceSinceLastRecord(){ - return (_lastPosition-GetPos()).Norm(); +double Pedestrian::GetDistanceSinceLastRecord() +{ + return (_lastPosition-GetPos()).Norm(); } -double Pedestrian::GetGlobalTime(){ - return _globalTime; +double Pedestrian::GetGlobalTime() +{ + return _globalTime; } -void Pedestrian::SetRouter(Router* router) { - _router=router; +void Pedestrian::SetRouter(Router* router) +{ + _router=router; } -Router* Pedestrian::GetRouter() const { - return _router; +Router* Pedestrian::GetRouter() const +{ + return _router; } -int Pedestrian::FindRoute() { - if( ! _router) { - Log->Write("ERROR:\t one or more routers does not exit! Check your router_ids"); - exit(EXIT_FAILURE); - } - return _router->FindExit(this); +int Pedestrian::FindRoute() +{ + if( ! _router) { + Log->Write("ERROR:\t one or more routers does not exit! Check your router_ids"); + exit(EXIT_FAILURE); + } + return _router->FindExit(this); } -double Pedestrian::GetElevation() const { - return _building->GetRoom(_roomID)->GetSubRoom(_subRoomID)->GetElevation(GetPos()); +double Pedestrian::GetElevation() const +{ + return _building->GetRoom(_roomID)->GetSubRoom(_subRoomID)->GetElevation(GetPos()); } -void Pedestrian::SetGlobalTime(double time){ - _globalTime=time; +void Pedestrian::SetGlobalTime(double time) +{ + _globalTime=time; } -double Pedestrian::GetPatienceTime() const { - return _patienceTime; +double Pedestrian::GetPatienceTime() const +{ + return _patienceTime; } -void Pedestrian::SetPatienceTime(double patienceTime) { - _patienceTime = patienceTime; +void Pedestrian::SetPatienceTime(double patienceTime) +{ + _patienceTime = patienceTime; } -const Building* Pedestrian::GetBuilding() { - return _building; +const Building* Pedestrian::GetBuilding() +{ + return _building; } -void Pedestrian::SetBuilding(Building* building) { - _building = building; +void Pedestrian::SetBuilding(Building* building) +{ + _building = building; } -void Pedestrian::SetSpotlight(bool spotlight){ - _spotlight=spotlight; +void Pedestrian::SetSpotlight(bool spotlight) +{ + _spotlight=spotlight; } -bool Pedestrian::GetSpotlight(){ - return !_enableSpotlight || _spotlight; +bool Pedestrian::GetSpotlight() +{ + return !_enableSpotlight || _spotlight; } -void Pedestrian::ActivateSpotlightSystem(bool status){ - _enableSpotlight=status; +void Pedestrian::ActivateSpotlightSystem(bool status) +{ + _enableSpotlight=status; } diff --git a/pedestrian/Pedestrian.h b/pedestrian/Pedestrian.h index e580a279da9d87d1ec24ca6356874841b460e91a..c08529bcf059bc31061c89d029983f4a7ff9ebd3 100644 --- a/pedestrian/Pedestrian.h +++ b/pedestrian/Pedestrian.h @@ -45,310 +45,310 @@ class Router; class Pedestrian { - private: - /// starting with 1 - int _id; - double _height; - double _age; - double _mass; // Mass: 1 - double _tau; // Reaction time: 0.5 - double _deltaT; // step size - std::string _gender; - - std::string _roomCaption; - int _roomID; - int _subRoomID; - int _exitIndex; // current exit - int _group; - - - NavLine* _navLine; // current exit line - std::map<int, int>_mentalMap; // map the actual room to a destination - std::vector<int> _destHistory; - std::vector<int> _trip; - Point _V0; //vector V0 - Point _lastPosition; - int _lastCellPosition; - - /** - * A set with UniqueIDs of closed crossings, - * transitions or hlines (hlines doesnt make that much sense, - * just that they are removed from the routing graph) - */ - std::map<int, NavLineState> _knownDoors; - - - //routing parameters - - /// new orientation after 10 seconds - double _reroutingThreshold; - /// a new orientation starts after this time - double _timeBeforeRerouting; - /// actual time im Jam - double _timeInJam; - /// time after which the ped feels to be in jam - double _patienceTime; - /// data from the last <_recordingTime> seconds will be kept - double _recordingTime; - /// store the last positions - std::queue <Point> _lastPositions; - /// store the last velocities - std::queue <Point> _lastVelocites; - - int _desiredFinalDestination; - int _oldRoomID; - int _oldSubRoomID; - int _newOrientationDelay; //2 seconds, in steps - - - /// necessary for smooth turning at sharp bend - int _updateRate; - double _turninAngle; - bool _reroutingEnabled; - bool _tmpFirstOrientation; // possibility to get rid of this variable - bool _newOrientationFlag; - - // the current time in the simulation - static double _globalTime; - static bool _enableSpotlight; - bool _spotlight; - - /// the router responsible for this pedestrian - Router* _router; - /// a pointer to the complete building - Building * _building; - /// the shape of this pedestrian - JEllipse _ellipse; - - - public: - // Konstruktoren - Pedestrian(); - virtual ~Pedestrian(); - - // Setter-Funktionen - void SetID(int i); - //TODO: use setRoom(Room*) and setSubRoom(SubRoom*) - void SetRoomID(int i, std::string roomCaption); - void SetSubRoomID(int i); - void SetMass(double m); - void SetTau(double tau); - void SetEllipse(const JEllipse& e); - void SetExitIndex(int i); - void SetExitLine(const NavLine* l); - void Setdt(double dt); - double Getdt(); - - - // Eigenschaften der Ellipse - void SetPos(const Point& pos); // setzt x und y-Koordinaten - void SetCellPos(int cp); - void SetV(const Point& v); // setzt x und y-Koordinaten der Geschwindigkeit - void SetV0Norm(double v0); - void SetSmoothTurning(bool smt); // activate the smooth turning with a delay of 2 sec - void SetPhiPed(); - void SetFinalDestination(int UID); - void SetTrip(const std::vector<int>& trip); - void SetRouter(Router* router); - - // Getter-Funktionen - const std::vector<int>& GetTrip() const; - int GetID() const; - int GetRoomID() const; - int GetSubRoomID() const; - double GetMass() const; - double GetTau() const; - const JEllipse& GetEllipse() const; - int GetExitIndex() const; - Router* GetRouter() const; - NavLine* GetExitLine() const; - - // Eigenschaften der Ellipse - const Point& GetPos() const; - int GetCellPos() const; - const Point& GetV() const; - const Point& GetV0() const; - const Point& GetV0(const Point& target); - - /** - * the desired speed is the projection of the speed on the horizontal plane. - * @return the norm of the desired speed. - */ - double GetV0Norm() const; - - - ///get axis in the walking direction - double GetLargerAxis() const; - ///get axis in the shoulder direction = orthogonal to the walking direction - double GetSmallerAxis() const; - double GetTimeInJam()const; - int GetFinalDestination() const; - void ClearMentalMap(); // erase the peds memory - - // functions for known closed Doors (needed for the Graphrouting and Rerouting) - void AddKnownClosedDoor(int door); - std::set<int> GetKnownClosedDoors(); - void MergeKnownClosedDoors(std::map<int, NavLineState> * input); - std::map<int, NavLineState> * GetKnownDoors(); - int DoorKnowledgeCount() const; - - - - int GetUniqueRoomID() const; - int GetNextDestination(); - int GetLastDestination(); - int GetDestinationCount(); - double GetDistanceToNextTarget() const; - double GetDisTanceToPreviousTarget() const; - - - - bool ChangedSubRoom(); - - void RecordActualPosition(); - double GetDistanceSinceLastRecord(); - - /** - * The elevation is computed using the plane equation given in the subroom. - * @return the z coordinate of the pedestrian. - */ - - double GetElevation() const; - - /** - * Compute and update the route. - * This method should be called at each time step; - * - * @return -1 if no route could be found. The ID of the - * next target is returned otherwise. - * - */ - int FindRoute(); - - ///write the pedestrian path (room and exit taken ) to file - void WritePath(std::ofstream& file, Building* building=NULL); - - ///write the pedestrian path (room and exit taken ) to file - /// in the format room1:exit1>room2:exit2 - std::string GetPath(); - - //debug - void Dump(int ID, int pa = 0); // dump pedestrians parameter, 0 for all parameters - - /** - * observe the reference pedestrians and collect some data, e.g distance to exit - * and average/maximal velocities - * - * @param maxObservationTime in sec. - * @return false, if the observation time is over and the observation data can be retrieved - */ - bool Observe(double maxObservationTime=-1); - - /** - * @return true, if reference pedestrian have been selected and the observation process has started - */ - bool IsObserving(); - - /** - * return the observation data in an array - * - * @param exitID, the concerned exit - * @param data, a float array to store the data - */ - void GetObservationData(int exitID, float* data); - - /** - * @return true if the time spent in jam exceed the patience time - * @see GetPatienceTime - */ - bool IsFeelingLikeInJam(); - - /** - * Set/Get the patience time. - * Higher value will cause the agent to almost never changes its current path. - * Small values will increase the frequency of looking for alternative - */ - double GetPatienceTime() const; - - /** - * Set/Get the patience time. - * Higher value will cause the agent to almost never changes its current path. - * Small values will increase the frequency of looking for alternative - */ - void SetPatienceTime(double patienceTime); - - /** - * Set/Get the spotlight value. If true, - * this pedestrians will be coloured and all other grey out. - * @param spotlight true for enabling, false for disabling - */ - void SetSpotlight(bool spotlight); - - - /** - * Set/Get the spotlight value. If true, - * this pedestrians will be coloured and all other grey out. - * @param spotlight true for enabling, false for disabling - */ - bool GetSpotlight(); - - - void ResetTimeInJam(); - void UpdateTimeInJam(); - void UpdateJamData(); - void UpdateReroutingTime(); - void RerouteIn(double time); - bool IsReadyForRerouting(); - - /** - * clear the parameter related to the re routing - */ - void ResetRerouting(); - - /** - * Set/Get the time period for which the data of the pedestrian should be kept. - * The results are used by the quickest path router - */ - void SetRecordingTime(double timeInSec); - - /** - * Set/Get the time period for which the data of the pedestrian should be kept - * The results are used by the quickest path router - */ - double GetRecordingTime() const; - - /** - * @return the average velocity over the recording period - */ - double GetAverageVelecityOverRecordingTime() const; - - double GetAge() const; - void SetAge(double age); - std::string GetGender() const; - void SetGender(std::string gender); - double GetHeight() const; - void SetHeight(double height); - int GetGroup() const; - void SetGroup(int group); - - static double GetGlobalTime(); - static void SetGlobalTime(double time); - - /** - * activate/deactivate the spotlight system - * @param status true for activating, false for deactivating - */ - static void ActivateSpotlightSystem(bool status); - - /** - * Set/Get the Building object - */ - const Building* GetBuilding(); - - /** - * Set/Get the Building object - */ - void SetBuilding(Building* building); +private: + /// starting with 1 + int _id; + double _height; + double _age; + double _mass; // Mass: 1 + double _tau; // Reaction time: 0.5 + double _deltaT; // step size + std::string _gender; + + std::string _roomCaption; + int _roomID; + int _subRoomID; + int _exitIndex; // current exit + int _group; + + + NavLine* _navLine; // current exit line + std::map<int, int>_mentalMap; // map the actual room to a destination + std::vector<int> _destHistory; + std::vector<int> _trip; + Point _V0; //vector V0 + Point _lastPosition; + int _lastCellPosition; + + /** + * A set with UniqueIDs of closed crossings, + * transitions or hlines (hlines doesnt make that much sense, + * just that they are removed from the routing graph) + */ + std::map<int, NavLineState> _knownDoors; + + + //routing parameters + + /// new orientation after 10 seconds + double _reroutingThreshold; + /// a new orientation starts after this time + double _timeBeforeRerouting; + /// actual time im Jam + double _timeInJam; + /// time after which the ped feels to be in jam + double _patienceTime; + /// data from the last <_recordingTime> seconds will be kept + double _recordingTime; + /// store the last positions + std::queue <Point> _lastPositions; + /// store the last velocities + std::queue <Point> _lastVelocites; + + int _desiredFinalDestination; + int _oldRoomID; + int _oldSubRoomID; + int _newOrientationDelay; //2 seconds, in steps + + + /// necessary for smooth turning at sharp bend + int _updateRate; + double _turninAngle; + bool _reroutingEnabled; + bool _tmpFirstOrientation; // possibility to get rid of this variable + bool _newOrientationFlag; + + // the current time in the simulation + static double _globalTime; + static bool _enableSpotlight; + bool _spotlight; + + /// the router responsible for this pedestrian + Router* _router; + /// a pointer to the complete building + Building * _building; + /// the shape of this pedestrian + JEllipse _ellipse; + + +public: + // Konstruktoren + Pedestrian(); + virtual ~Pedestrian(); + + // Setter-Funktionen + void SetID(int i); + //TODO: use setRoom(Room*) and setSubRoom(SubRoom*) + void SetRoomID(int i, std::string roomCaption); + void SetSubRoomID(int i); + void SetMass(double m); + void SetTau(double tau); + void SetEllipse(const JEllipse& e); + void SetExitIndex(int i); + void SetExitLine(const NavLine* l); + void Setdt(double dt); + double Getdt(); + + + // Eigenschaften der Ellipse + void SetPos(const Point& pos); // setzt x und y-Koordinaten + void SetCellPos(int cp); + void SetV(const Point& v); // setzt x und y-Koordinaten der Geschwindigkeit + void SetV0Norm(double v0); + void SetSmoothTurning(bool smt); // activate the smooth turning with a delay of 2 sec + void SetPhiPed(); + void SetFinalDestination(int UID); + void SetTrip(const std::vector<int>& trip); + void SetRouter(Router* router); + + // Getter-Funktionen + const std::vector<int>& GetTrip() const; + int GetID() const; + int GetRoomID() const; + int GetSubRoomID() const; + double GetMass() const; + double GetTau() const; + const JEllipse& GetEllipse() const; + int GetExitIndex() const; + Router* GetRouter() const; + NavLine* GetExitLine() const; + + // Eigenschaften der Ellipse + const Point& GetPos() const; + int GetCellPos() const; + const Point& GetV() const; + const Point& GetV0() const; + const Point& GetV0(const Point& target); + + /** + * the desired speed is the projection of the speed on the horizontal plane. + * @return the norm of the desired speed. + */ + double GetV0Norm() const; + + + ///get axis in the walking direction + double GetLargerAxis() const; + ///get axis in the shoulder direction = orthogonal to the walking direction + double GetSmallerAxis() const; + double GetTimeInJam()const; + int GetFinalDestination() const; + void ClearMentalMap(); // erase the peds memory + + // functions for known closed Doors (needed for the Graphrouting and Rerouting) + void AddKnownClosedDoor(int door); + std::set<int> GetKnownClosedDoors(); + void MergeKnownClosedDoors(std::map<int, NavLineState> * input); + std::map<int, NavLineState> * GetKnownDoors(); + int DoorKnowledgeCount() const; + + + + int GetUniqueRoomID() const; + int GetNextDestination(); + int GetLastDestination(); + int GetDestinationCount(); + double GetDistanceToNextTarget() const; + double GetDisTanceToPreviousTarget() const; + + + + bool ChangedSubRoom(); + + void RecordActualPosition(); + double GetDistanceSinceLastRecord(); + + /** + * The elevation is computed using the plane equation given in the subroom. + * @return the z coordinate of the pedestrian. + */ + + double GetElevation() const; + + /** + * Compute and update the route. + * This method should be called at each time step; + * + * @return -1 if no route could be found. The ID of the + * next target is returned otherwise. + * + */ + int FindRoute(); + + ///write the pedestrian path (room and exit taken ) to file + void WritePath(std::ofstream& file, Building* building=NULL); + + ///write the pedestrian path (room and exit taken ) to file + /// in the format room1:exit1>room2:exit2 + std::string GetPath(); + + //debug + void Dump(int ID, int pa = 0); // dump pedestrians parameter, 0 for all parameters + + /** + * observe the reference pedestrians and collect some data, e.g distance to exit + * and average/maximal velocities + * + * @param maxObservationTime in sec. + * @return false, if the observation time is over and the observation data can be retrieved + */ + bool Observe(double maxObservationTime=-1); + + /** + * @return true, if reference pedestrian have been selected and the observation process has started + */ + bool IsObserving(); + + /** + * return the observation data in an array + * + * @param exitID, the concerned exit + * @param data, a float array to store the data + */ + void GetObservationData(int exitID, float* data); + + /** + * @return true if the time spent in jam exceed the patience time + * @see GetPatienceTime + */ + bool IsFeelingLikeInJam(); + + /** + * Set/Get the patience time. + * Higher value will cause the agent to almost never changes its current path. + * Small values will increase the frequency of looking for alternative + */ + double GetPatienceTime() const; + + /** + * Set/Get the patience time. + * Higher value will cause the agent to almost never changes its current path. + * Small values will increase the frequency of looking for alternative + */ + void SetPatienceTime(double patienceTime); + + /** + * Set/Get the spotlight value. If true, + * this pedestrians will be coloured and all other grey out. + * @param spotlight true for enabling, false for disabling + */ + void SetSpotlight(bool spotlight); + + + /** + * Set/Get the spotlight value. If true, + * this pedestrians will be coloured and all other grey out. + * @param spotlight true for enabling, false for disabling + */ + bool GetSpotlight(); + + + void ResetTimeInJam(); + void UpdateTimeInJam(); + void UpdateJamData(); + void UpdateReroutingTime(); + void RerouteIn(double time); + bool IsReadyForRerouting(); + + /** + * clear the parameter related to the re routing + */ + void ResetRerouting(); + + /** + * Set/Get the time period for which the data of the pedestrian should be kept. + * The results are used by the quickest path router + */ + void SetRecordingTime(double timeInSec); + + /** + * Set/Get the time period for which the data of the pedestrian should be kept + * The results are used by the quickest path router + */ + double GetRecordingTime() const; + + /** + * @return the average velocity over the recording period + */ + double GetAverageVelecityOverRecordingTime() const; + + double GetAge() const; + void SetAge(double age); + std::string GetGender() const; + void SetGender(std::string gender); + double GetHeight() const; + void SetHeight(double height); + int GetGroup() const; + void SetGroup(int group); + + static double GetGlobalTime(); + static void SetGlobalTime(double time); + + /** + * activate/deactivate the spotlight system + * @param status true for activating, false for deactivating + */ + static void ActivateSpotlightSystem(bool status); + + /** + * Set/Get the Building object + */ + const Building* GetBuilding(); + + /** + * Set/Get the Building object + */ + void SetBuilding(Building* building); }; #endif /* _PEDESTRIAN_H */ diff --git a/poly2tri/common/shapes.cpp b/poly2tri/common/shapes.cpp index 1e232cc63278e23348c6432f065308fcd8faff78..1f36ae32a88c21ff19cdeaa819520cdcf463c44f 100644 --- a/poly2tri/common/shapes.cpp +++ b/poly2tri/common/shapes.cpp @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * http://code.google.com/p/poly2tri/ * @@ -35,39 +35,43 @@ namespace p2t { Triangle::Triangle(Point& a, Point& b, Point& c) { - points_[0] = &a; points_[1] = &b; points_[2] = &c; - neighbors_[0] = NULL; neighbors_[1] = NULL; neighbors_[2] = NULL; - constrained_edge[0] = constrained_edge[1] = constrained_edge[2] = false; - delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; - interior_ = false; + points_[0] = &a; + points_[1] = &b; + points_[2] = &c; + neighbors_[0] = NULL; + neighbors_[1] = NULL; + neighbors_[2] = NULL; + constrained_edge[0] = constrained_edge[1] = constrained_edge[2] = false; + delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; + interior_ = false; } // Update neighbor pointers void Triangle::MarkNeighbor(Point* p1, Point* p2, Triangle* t) { - if ((p1 == points_[2] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[2])) - neighbors_[0] = t; - else if ((p1 == points_[0] && p2 == points_[2]) || (p1 == points_[2] && p2 == points_[0])) - neighbors_[1] = t; - else if ((p1 == points_[0] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[0])) - neighbors_[2] = t; - else - assert(0); + if ((p1 == points_[2] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[2])) + neighbors_[0] = t; + else if ((p1 == points_[0] && p2 == points_[2]) || (p1 == points_[2] && p2 == points_[0])) + neighbors_[1] = t; + else if ((p1 == points_[0] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[0])) + neighbors_[2] = t; + else + assert(0); } // Exhaustive search to update neighbor pointers void Triangle::MarkNeighbor(Triangle& t) { - if (t.Contains(points_[1], points_[2])) { - neighbors_[0] = &t; - t.MarkNeighbor(points_[1], points_[2], this); - } else if (t.Contains(points_[0], points_[2])) { - neighbors_[1] = &t; - t.MarkNeighbor(points_[0], points_[2], this); - } else if (t.Contains(points_[0], points_[1])) { - neighbors_[2] = &t; - t.MarkNeighbor(points_[0], points_[1], this); - } + if (t.Contains(points_[1], points_[2])) { + neighbors_[0] = &t; + t.MarkNeighbor(points_[1], points_[2], this); + } else if (t.Contains(points_[0], points_[2])) { + neighbors_[1] = &t; + t.MarkNeighbor(points_[0], points_[2], this); + } else if (t.Contains(points_[0], points_[1])) { + neighbors_[2] = &t; + t.MarkNeighbor(points_[0], points_[1], this); + } } /** @@ -75,295 +79,288 @@ void Triangle::MarkNeighbor(Triangle& t) */ void Triangle::Clear() { - Triangle *t; - for( int i=0; i<3; i++ ) - { - t = neighbors_[i]; - if( t != NULL ) - { - t->ClearNeighbor( this ); - } - } - ClearNeighbors(); - points_[0]=points_[1]=points_[2] = NULL; + Triangle *t; + for( int i=0; i<3; i++ ) { + t = neighbors_[i]; + if( t != NULL ) { + t->ClearNeighbor( this ); + } + } + ClearNeighbors(); + points_[0]=points_[1]=points_[2] = NULL; } void Triangle::ClearNeighbor(Triangle *triangle ) { - if( neighbors_[0] == triangle ) - { - neighbors_[0] = NULL; - } - else if( neighbors_[1] == triangle ) - { - neighbors_[1] = NULL; - } - else - { - neighbors_[2] = NULL; - } + if( neighbors_[0] == triangle ) { + neighbors_[0] = NULL; + } else if( neighbors_[1] == triangle ) { + neighbors_[1] = NULL; + } else { + neighbors_[2] = NULL; + } } - + void Triangle::ClearNeighbors() { - neighbors_[0] = NULL; - neighbors_[1] = NULL; - neighbors_[2] = NULL; + neighbors_[0] = NULL; + neighbors_[1] = NULL; + neighbors_[2] = NULL; } void Triangle::ClearDelunayEdges() { - delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; + delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false; } Point* Triangle::OppositePoint(Triangle& t, Point& p) { - Point *cw = t.PointCW(p); + Point *cw = t.PointCW(p); // double x = cw->x; // double y = cw->y; // x = p.x; // y = p.y; - return PointCW(*cw); + return PointCW(*cw); } // Legalized triangle by rotating clockwise around point(0) void Triangle::Legalize(Point& point) { - points_[1] = points_[0]; - points_[0] = points_[2]; - points_[2] = &point; + points_[1] = points_[0]; + points_[0] = points_[2]; + points_[2] = &point; } // Legalize triagnle by rotating clockwise around oPoint void Triangle::Legalize(Point& opoint, Point& npoint) { - if (&opoint == points_[0]) { - points_[1] = points_[0]; - points_[0] = points_[2]; - points_[2] = &npoint; - } else if (&opoint == points_[1]) { - points_[2] = points_[1]; - points_[1] = points_[0]; - points_[0] = &npoint; - } else if (&opoint == points_[2]) { - points_[0] = points_[2]; - points_[2] = points_[1]; - points_[1] = &npoint; - } else { - assert(0); - } + if (&opoint == points_[0]) { + points_[1] = points_[0]; + points_[0] = points_[2]; + points_[2] = &npoint; + } else if (&opoint == points_[1]) { + points_[2] = points_[1]; + points_[1] = points_[0]; + points_[0] = &npoint; + } else if (&opoint == points_[2]) { + points_[0] = points_[2]; + points_[2] = points_[1]; + points_[1] = &npoint; + } else { + assert(0); + } } int Triangle::Index(const Point* p) { - if (p == points_[0]) { - return 0; - } else if (p == points_[1]) { - return 1; - } else if (p == points_[2]) { - return 2; - } - assert(0); - return -1; // just to et rid of some warnings + if (p == points_[0]) { + return 0; + } else if (p == points_[1]) { + return 1; + } else if (p == points_[2]) { + return 2; + } + assert(0); + return -1; // just to et rid of some warnings } int Triangle::EdgeIndex(const Point* p1, const Point* p2) { - if (points_[0] == p1) { - if (points_[1] == p2) { - return 2; - } else if (points_[2] == p2) { - return 1; - } - } else if (points_[1] == p1) { - if (points_[2] == p2) { - return 0; - } else if (points_[0] == p2) { - return 2; - } - } else if (points_[2] == p1) { - if (points_[0] == p2) { - return 1; - } else if (points_[1] == p2) { - return 0; - } - } - return -1; + if (points_[0] == p1) { + if (points_[1] == p2) { + return 2; + } else if (points_[2] == p2) { + return 1; + } + } else if (points_[1] == p1) { + if (points_[2] == p2) { + return 0; + } else if (points_[0] == p2) { + return 2; + } + } else if (points_[2] == p1) { + if (points_[0] == p2) { + return 1; + } else if (points_[1] == p2) { + return 0; + } + } + return -1; } void Triangle::MarkConstrainedEdge(const int index) { - constrained_edge[index] = true; + constrained_edge[index] = true; } void Triangle::MarkConstrainedEdge(Edge& edge) { - MarkConstrainedEdge(edge.p, edge.q); + MarkConstrainedEdge(edge.p, edge.q); } // Mark edge as constrained void Triangle::MarkConstrainedEdge(Point* p, Point* q) { - if ((q == points_[0] && p == points_[1]) || (q == points_[1] && p == points_[0])) { - constrained_edge[2] = true; - } else if ((q == points_[0] && p == points_[2]) || (q == points_[2] && p == points_[0])) { - constrained_edge[1] = true; - } else if ((q == points_[1] && p == points_[2]) || (q == points_[2] && p == points_[1])) { - constrained_edge[0] = true; - } + if ((q == points_[0] && p == points_[1]) || (q == points_[1] && p == points_[0])) { + constrained_edge[2] = true; + } else if ((q == points_[0] && p == points_[2]) || (q == points_[2] && p == points_[0])) { + constrained_edge[1] = true; + } else if ((q == points_[1] && p == points_[2]) || (q == points_[2] && p == points_[1])) { + constrained_edge[0] = true; + } } // The point counter-clockwise to given point Point* Triangle::PointCW(Point& point) { - if (&point == points_[0]) { - return points_[2]; - } else if (&point == points_[1]) { - return points_[0]; - } else if (&point == points_[2]) { - return points_[1]; - } - assert(0); - return NULL; + if (&point == points_[0]) { + return points_[2]; + } else if (&point == points_[1]) { + return points_[0]; + } else if (&point == points_[2]) { + return points_[1]; + } + assert(0); + return NULL; } // The point counter-clockwise to given point Point* Triangle::PointCCW(Point& point) { - if (&point == points_[0]) { - return points_[1]; - } else if (&point == points_[1]) { - return points_[2]; - } else if (&point == points_[2]) { - return points_[0]; - } - assert(0); - return NULL; + if (&point == points_[0]) { + return points_[1]; + } else if (&point == points_[1]) { + return points_[2]; + } else if (&point == points_[2]) { + return points_[0]; + } + assert(0); + return NULL; } // The neighbor clockwise to given point Triangle* Triangle::NeighborCW(Point& point) { - if (&point == points_[0]) { - return neighbors_[1]; - } else if (&point == points_[1]) { - return neighbors_[2]; - } - return neighbors_[0]; + if (&point == points_[0]) { + return neighbors_[1]; + } else if (&point == points_[1]) { + return neighbors_[2]; + } + return neighbors_[0]; } // The neighbor counter-clockwise to given point Triangle* Triangle::NeighborCCW(Point& point) { - if (&point == points_[0]) { - return neighbors_[2]; - } else if (&point == points_[1]) { - return neighbors_[0]; - } - return neighbors_[1]; + if (&point == points_[0]) { + return neighbors_[2]; + } else if (&point == points_[1]) { + return neighbors_[0]; + } + return neighbors_[1]; } bool Triangle::GetConstrainedEdgeCCW(Point& p) { - if (&p == points_[0]) { - return constrained_edge[2]; - } else if (&p == points_[1]) { - return constrained_edge[0]; - } - return constrained_edge[1]; + if (&p == points_[0]) { + return constrained_edge[2]; + } else if (&p == points_[1]) { + return constrained_edge[0]; + } + return constrained_edge[1]; } bool Triangle::GetConstrainedEdgeCW(Point& p) { - if (&p == points_[0]) { - return constrained_edge[1]; - } else if (&p == points_[1]) { - return constrained_edge[2]; - } - return constrained_edge[0]; + if (&p == points_[0]) { + return constrained_edge[1]; + } else if (&p == points_[1]) { + return constrained_edge[2]; + } + return constrained_edge[0]; } void Triangle::SetConstrainedEdgeCCW(Point& p, bool ce) { - if (&p == points_[0]) { - constrained_edge[2] = ce; - } else if (&p == points_[1]) { - constrained_edge[0] = ce; - } else { - constrained_edge[1] = ce; - } + if (&p == points_[0]) { + constrained_edge[2] = ce; + } else if (&p == points_[1]) { + constrained_edge[0] = ce; + } else { + constrained_edge[1] = ce; + } } void Triangle::SetConstrainedEdgeCW(Point& p, bool ce) { - if (&p == points_[0]) { - constrained_edge[1] = ce; - } else if (&p == points_[1]) { - constrained_edge[2] = ce; - } else { - constrained_edge[0] = ce; - } + if (&p == points_[0]) { + constrained_edge[1] = ce; + } else if (&p == points_[1]) { + constrained_edge[2] = ce; + } else { + constrained_edge[0] = ce; + } } bool Triangle::GetDelunayEdgeCCW(Point& p) { - if (&p == points_[0]) { - return delaunay_edge[2]; - } else if (&p == points_[1]) { - return delaunay_edge[0]; - } - return delaunay_edge[1]; + if (&p == points_[0]) { + return delaunay_edge[2]; + } else if (&p == points_[1]) { + return delaunay_edge[0]; + } + return delaunay_edge[1]; } bool Triangle::GetDelunayEdgeCW(Point& p) { - if (&p == points_[0]) { - return delaunay_edge[1]; - } else if (&p == points_[1]) { - return delaunay_edge[2]; - } - return delaunay_edge[0]; + if (&p == points_[0]) { + return delaunay_edge[1]; + } else if (&p == points_[1]) { + return delaunay_edge[2]; + } + return delaunay_edge[0]; } void Triangle::SetDelunayEdgeCCW(Point& p, bool e) { - if (&p == points_[0]) { - delaunay_edge[2] = e; - } else if (&p == points_[1]) { - delaunay_edge[0] = e; - } else { - delaunay_edge[1] = e; - } + if (&p == points_[0]) { + delaunay_edge[2] = e; + } else if (&p == points_[1]) { + delaunay_edge[0] = e; + } else { + delaunay_edge[1] = e; + } } void Triangle::SetDelunayEdgeCW(Point& p, bool e) { - if (&p == points_[0]) { - delaunay_edge[1] = e; - } else if (&p == points_[1]) { - delaunay_edge[2] = e; - } else { - delaunay_edge[0] = e; - } + if (&p == points_[0]) { + delaunay_edge[1] = e; + } else if (&p == points_[1]) { + delaunay_edge[2] = e; + } else { + delaunay_edge[0] = e; + } } // The neighbor across to given point Triangle& Triangle::NeighborAcross(Point& opoint) { - if (&opoint == points_[0]) { - return *neighbors_[0]; - } else if (&opoint == points_[1]) { - return *neighbors_[1]; - } - return *neighbors_[2]; + if (&opoint == points_[0]) { + return *neighbors_[0]; + } else if (&opoint == points_[1]) { + return *neighbors_[1]; + } + return *neighbors_[2]; } void Triangle::DebugPrint() { - using namespace std; - cout << points_[0]->x << "," << points_[0]->y << " "; - cout << points_[1]->x << "," << points_[1]->y << " "; - cout << points_[2]->x << "," << points_[2]->y << endl; + using namespace std; + cout << points_[0]->x << "," << points_[0]->y << " "; + cout << points_[1]->x << "," << points_[1]->y << " "; + cout << points_[2]->x << "," << points_[2]->y << endl; } } diff --git a/poly2tri/common/shapes.h b/poly2tri/common/shapes.h index d3761def2ecd4f0e4b3b8d7c4569f65d73d0b950..97e58dd5c0d9c3ecc6fbb2b1d2cc29e4ee234af8 100644 --- a/poly2tri/common/shapes.h +++ b/poly2tri/common/shapes.h @@ -40,283 +40,273 @@ namespace p2t { - struct Edge; - - struct Point { - - double x, y; - - /// Default constructor does nothing (for performance). - Point() - { - x = 0.0; - y = 0.0; - } - - /// The edges this point constitutes an upper ending point - std::vector<Edge*> edge_list; - - /// Construct using coordinates. - Point(double x, double y) : x(x), y(y) {} - - /// Set this point to all zeros. - void set_zero() - { - x = 0.0; - y = 0.0; - } - - /// Set this point to some specified coordinates. - void set(double x_, double y_) - { - x = x_; - y = y_; - } - - /// Negate this point. - Point operator -() const - { - Point v; - v.set(-x, -y); - return v; - } - - /// Add a point to this point. - void operator +=(const Point& v) - { - x += v.x; - y += v.y; - } - - /// Subtract a point from this point. - void operator -=(const Point& v) - { - x -= v.x; - y -= v.y; - } - - /// Multiply this point by a scalar. - void operator *=(double a) - { - x *= a; - y *= a; - } - - /// Get the length of this point (the norm). - double Length() const - { - return sqrt(x * x + y * y); - } - - /// Convert this point into a unit point. Returns the Length. - double Normalize() - { - double len = Length(); - x /= len; - y /= len; - return len; - } - - }; - - // Represents a simple polygon's edge - struct Edge { - - Point* p, *q; - - /// Constructor - Edge(Point& p1, Point& p2) : p(&p1), q(&p2) - { - if (p1.y > p2.y) { - q = &p1; - p = &p2; - } else if (p1.y == p2.y) { - if (p1.x > p2.x) { - q = &p1; - p = &p2; - } else if (p1.x == p2.x) { - // Repeat points - assert(false); - } - } - - q->edge_list.push_back(this); - } - }; - - // Triangle-based data structures are know to have better performance than quad-edge structures - // See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator" - // "Triangulations in CGAL" - class Triangle { - public: - - /// Constructor - Triangle(Point& a, Point& b, Point& c); - - /// Flags to determine if an edge is a Constrained edge - bool constrained_edge[3]; - /// Flags to determine if an edge is a Delauney edge - bool delaunay_edge[3]; - - Point* GetPoint(const int& index); - Point* PointCW(Point& point); - Point* PointCCW(Point& point); - Point* OppositePoint(Triangle& t, Point& p); - - Triangle* GetNeighbor(const int& index); - void MarkNeighbor(Point* p1, Point* p2, Triangle* t); - void MarkNeighbor(Triangle& t); - - void MarkConstrainedEdge(const int index); - void MarkConstrainedEdge(Edge& edge); - void MarkConstrainedEdge(Point* p, Point* q); - - int Index(const Point* p); - int EdgeIndex(const Point* p1, const Point* p2); - - Triangle* NeighborCW(Point& point); - Triangle* NeighborCCW(Point& point); - bool GetConstrainedEdgeCCW(Point& p); - bool GetConstrainedEdgeCW(Point& p); - void SetConstrainedEdgeCCW(Point& p, bool ce); - void SetConstrainedEdgeCW(Point& p, bool ce); - bool GetDelunayEdgeCCW(Point& p); - bool GetDelunayEdgeCW(Point& p); - void SetDelunayEdgeCCW(Point& p, bool e); - void SetDelunayEdgeCW(Point& p, bool e); - - bool Contains(Point* p); - bool Contains(const Edge& e); - bool Contains(Point* p, Point* q); - void Legalize(Point& point); - void Legalize(Point& opoint, Point& npoint); - /** - * Clears all references to all other triangles and points - */ - void Clear(); - void ClearNeighbor(Triangle *triangle ); - void ClearNeighbors(); - void ClearDelunayEdges(); - - inline bool IsInterior(); - inline void IsInterior(bool b); - - Triangle& NeighborAcross(Point& opoint); - - void DebugPrint(); - - private: - - /// Triangle points - Point* points_[3]; - /// Neighbor list - Triangle* neighbors_[3]; - - /// Has this triangle been marked as an interior triangle? - bool interior_; - }; - - inline bool cmp(const Point* a, const Point* b) - { - if (a->y < b->y) { - return true; - } else if (a->y == b->y) { - // Make sure q is point with greater x value - if (a->x < b->x) { - return true; - } - } - return false; - } - - /// Add two points_ component-wise. - inline Point operator +(const Point& a, const Point& b) - { - return Point(a.x + b.x, a.y + b.y); - } - - /// Subtract two points_ component-wise. - inline Point operator -(const Point& a, const Point& b) - { - return Point(a.x - b.x, a.y - b.y); - } - - /// Multiply point by scalar - inline Point operator *(double s, const Point& a) - { - return Point(s * a.x, s * a.y); - } - - inline bool operator ==(const Point& a, const Point& b) - { - return a.x == b.x && a.y == b.y; - } - - inline bool operator !=(const Point& a, const Point& b) - { - return !(a.x == b.x) && !(a.y == b.y); - } - - /// Peform the dot product on two vectors. - inline double Dot(const Point& a, const Point& b) - { - return a.x * b.x + a.y * b.y; - } - - /// Perform the cross product on two vectors. In 2D this produces a scalar. - inline double Cross(const Point& a, const Point& b) - { - return a.x * b.y - a.y * b.x; - } - - /// Perform the cross product on a point and a scalar. In 2D this produces - /// a point. - inline Point Cross(const Point& a, double s) - { - return Point(s * a.y, -s * a.x); - } - - /// Perform the cross product on a scalar and a point. In 2D this produces - /// a point. - inline Point Cross(const double s, const Point& a) - { - return Point(-s * a.y, s * a.x); - } - - inline Point* Triangle::GetPoint(const int& index) - { - return points_[index]; - } - - inline Triangle* Triangle::GetNeighbor(const int& index) - { - return neighbors_[index]; - } - - inline bool Triangle::Contains(Point* p) - { - return p == points_[0] || p == points_[1] || p == points_[2]; - } - - inline bool Triangle::Contains(const Edge& e) - { - return Contains(e.p) && Contains(e.q); - } - - inline bool Triangle::Contains(Point* p, Point* q) - { - return Contains(p) && Contains(q); - } - - inline bool Triangle::IsInterior() - { - return interior_; - } - - inline void Triangle::IsInterior(bool b) - { - interior_ = b; - } +struct Edge; + +struct Point { + + double x, y; + + /// Default constructor does nothing (for performance). + Point() { + x = 0.0; + y = 0.0; + } + + /// The edges this point constitutes an upper ending point + std::vector<Edge*> edge_list; + + /// Construct using coordinates. + Point(double x, double y) : x(x), y(y) {} + + /// Set this point to all zeros. + void set_zero() { + x = 0.0; + y = 0.0; + } + + /// Set this point to some specified coordinates. + void set(double x_, double y_) { + x = x_; + y = y_; + } + + /// Negate this point. + Point operator -() const { + Point v; + v.set(-x, -y); + return v; + } + + /// Add a point to this point. + void operator +=(const Point& v) { + x += v.x; + y += v.y; + } + + /// Subtract a point from this point. + void operator -=(const Point& v) { + x -= v.x; + y -= v.y; + } + + /// Multiply this point by a scalar. + void operator *=(double a) { + x *= a; + y *= a; + } + + /// Get the length of this point (the norm). + double Length() const { + return sqrt(x * x + y * y); + } + + /// Convert this point into a unit point. Returns the Length. + double Normalize() { + double len = Length(); + x /= len; + y /= len; + return len; + } + +}; + +// Represents a simple polygon's edge +struct Edge { + + Point* p, *q; + + /// Constructor + Edge(Point& p1, Point& p2) : p(&p1), q(&p2) { + if (p1.y > p2.y) { + q = &p1; + p = &p2; + } else if (p1.y == p2.y) { + if (p1.x > p2.x) { + q = &p1; + p = &p2; + } else if (p1.x == p2.x) { + // Repeat points + assert(false); + } + } + + q->edge_list.push_back(this); + } +}; + +// Triangle-based data structures are know to have better performance than quad-edge structures +// See: J. Shewchuk, "Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator" +// "Triangulations in CGAL" +class Triangle { +public: + + /// Constructor + Triangle(Point& a, Point& b, Point& c); + + /// Flags to determine if an edge is a Constrained edge + bool constrained_edge[3]; + /// Flags to determine if an edge is a Delauney edge + bool delaunay_edge[3]; + + Point* GetPoint(const int& index); + Point* PointCW(Point& point); + Point* PointCCW(Point& point); + Point* OppositePoint(Triangle& t, Point& p); + + Triangle* GetNeighbor(const int& index); + void MarkNeighbor(Point* p1, Point* p2, Triangle* t); + void MarkNeighbor(Triangle& t); + + void MarkConstrainedEdge(const int index); + void MarkConstrainedEdge(Edge& edge); + void MarkConstrainedEdge(Point* p, Point* q); + + int Index(const Point* p); + int EdgeIndex(const Point* p1, const Point* p2); + + Triangle* NeighborCW(Point& point); + Triangle* NeighborCCW(Point& point); + bool GetConstrainedEdgeCCW(Point& p); + bool GetConstrainedEdgeCW(Point& p); + void SetConstrainedEdgeCCW(Point& p, bool ce); + void SetConstrainedEdgeCW(Point& p, bool ce); + bool GetDelunayEdgeCCW(Point& p); + bool GetDelunayEdgeCW(Point& p); + void SetDelunayEdgeCCW(Point& p, bool e); + void SetDelunayEdgeCW(Point& p, bool e); + + bool Contains(Point* p); + bool Contains(const Edge& e); + bool Contains(Point* p, Point* q); + void Legalize(Point& point); + void Legalize(Point& opoint, Point& npoint); + /** + * Clears all references to all other triangles and points + */ + void Clear(); + void ClearNeighbor(Triangle *triangle ); + void ClearNeighbors(); + void ClearDelunayEdges(); + + inline bool IsInterior(); + inline void IsInterior(bool b); + + Triangle& NeighborAcross(Point& opoint); + + void DebugPrint(); + +private: + + /// Triangle points + Point* points_[3]; + /// Neighbor list + Triangle* neighbors_[3]; + + /// Has this triangle been marked as an interior triangle? + bool interior_; +}; + +inline bool cmp(const Point* a, const Point* b) +{ + if (a->y < b->y) { + return true; + } else if (a->y == b->y) { + // Make sure q is point with greater x value + if (a->x < b->x) { + return true; + } + } + return false; +} + +/// Add two points_ component-wise. +inline Point operator +(const Point& a, const Point& b) +{ + return Point(a.x + b.x, a.y + b.y); +} + +/// Subtract two points_ component-wise. +inline Point operator -(const Point& a, const Point& b) +{ + return Point(a.x - b.x, a.y - b.y); +} + +/// Multiply point by scalar +inline Point operator *(double s, const Point& a) +{ + return Point(s * a.x, s * a.y); +} + +inline bool operator ==(const Point& a, const Point& b) +{ + return a.x == b.x && a.y == b.y; +} + +inline bool operator !=(const Point& a, const Point& b) +{ + return !(a.x == b.x) && !(a.y == b.y); +} + +/// Peform the dot product on two vectors. +inline double Dot(const Point& a, const Point& b) +{ + return a.x * b.x + a.y * b.y; +} + +/// Perform the cross product on two vectors. In 2D this produces a scalar. +inline double Cross(const Point& a, const Point& b) +{ + return a.x * b.y - a.y * b.x; +} + +/// Perform the cross product on a point and a scalar. In 2D this produces +/// a point. +inline Point Cross(const Point& a, double s) +{ + return Point(s * a.y, -s * a.x); +} + +/// Perform the cross product on a scalar and a point. In 2D this produces +/// a point. +inline Point Cross(const double s, const Point& a) +{ + return Point(-s * a.y, s * a.x); +} + +inline Point* Triangle::GetPoint(const int& index) +{ + return points_[index]; +} + +inline Triangle* Triangle::GetNeighbor(const int& index) +{ + return neighbors_[index]; +} + +inline bool Triangle::Contains(Point* p) +{ + return p == points_[0] || p == points_[1] || p == points_[2]; +} + +inline bool Triangle::Contains(const Edge& e) +{ + return Contains(e.p) && Contains(e.q); +} + +inline bool Triangle::Contains(Point* p, Point* q) +{ + return Contains(p) && Contains(q); +} + +inline bool Triangle::IsInterior() +{ + return interior_; +} + +inline void Triangle::IsInterior(bool b) +{ + interior_ = b; +} } diff --git a/poly2tri/common/utils.h b/poly2tri/common/utils.h index cccfabf03c054f73e5b8ed692210a614508bc59a..32b5266cb761af59b6a5beb78895f6e42537c540 100644 --- a/poly2tri/common/utils.h +++ b/poly2tri/common/utils.h @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * http://code.google.com/p/poly2tri/ * @@ -28,7 +28,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - + #ifndef UTILS_H #define UTILS_H @@ -40,82 +40,82 @@ namespace p2t { - const double PI_3div4 = 3 * M_PI / 4; - const double PI_div2 = 1.57079632679489661923; - const double EPSILON = 1e-12; - - enum Orientation { CW, CCW, COLLINEAR }; - - /** - * Forumla to calculate signed area<br> - * Positive if CCW<br> - * Negative if CW<br> - * 0 if collinear<br> - * <pre> - * A[P1,P2,P3] = (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1) - * = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3) - * </pre> - */ - Orientation Orient2d(Point& pa, Point& pb, Point& pc) +const double PI_3div4 = 3 * M_PI / 4; +const double PI_div2 = 1.57079632679489661923; +const double EPSILON = 1e-12; + +enum Orientation { CW, CCW, COLLINEAR }; + +/** + * Forumla to calculate signed area<br> + * Positive if CCW<br> + * Negative if CW<br> + * 0 if collinear<br> + * <pre> + * A[P1,P2,P3] = (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1) + * = (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3) + * </pre> + */ +Orientation Orient2d(Point& pa, Point& pb, Point& pc) +{ + double detleft = (pa.x - pc.x) * (pb.y - pc.y); + double detright = (pa.y - pc.y) * (pb.x - pc.x); + double val = detleft - detright; + if (val > -EPSILON && val < EPSILON) { + return COLLINEAR; + } else if (val > 0) { + return CCW; + } + return CW; +} + +/* + bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) { - double detleft = (pa.x - pc.x) * (pb.y - pc.y); - double detright = (pa.y - pc.y) * (pb.x - pc.x); - double val = detleft - detright; - if (val > -EPSILON && val < EPSILON) { - return COLLINEAR; - } else if (val > 0) { - return CCW; - } - return CW; + double pdx = pd.x; + double pdy = pd.y; + double adx = pa.x - pdx; + double ady = pa.y - pdy; + double bdx = pb.x - pdx; + double bdy = pb.y - pdy; + + double adxbdy = adx * bdy; + double bdxady = bdx * ady; + double oabd = adxbdy - bdxady; + + if (oabd <= EPSILON) { + return false; } - /* - bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) - { - double pdx = pd.x; - double pdy = pd.y; - double adx = pa.x - pdx; - double ady = pa.y - pdy; - double bdx = pb.x - pdx; - double bdy = pb.y - pdy; - - double adxbdy = adx * bdy; - double bdxady = bdx * ady; - double oabd = adxbdy - bdxady; - - if (oabd <= EPSILON) { - return false; - } + double cdx = pc.x - pdx; + double cdy = pc.y - pdy; - double cdx = pc.x - pdx; - double cdy = pc.y - pdy; + double cdxady = cdx * ady; + double adxcdy = adx * cdy; + double ocad = cdxady - adxcdy; - double cdxady = cdx * ady; - double adxcdy = adx * cdy; - double ocad = cdxady - adxcdy; + if (ocad <= EPSILON) { + return false; + } - if (ocad <= EPSILON) { - return false; - } + return true; + } - return true; - } +*/ - */ +bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) +{ + double oadb = (pa.x - pb.x)*(pd.y - pb.y) - (pd.x - pb.x)*(pa.y - pb.y); + if (oadb >= -EPSILON) { + return false; + } - bool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd) - { - double oadb = (pa.x - pb.x)*(pd.y - pb.y) - (pd.x - pb.x)*(pa.y - pb.y); - if (oadb >= -EPSILON) { - return false; - } - - double oadc = (pa.x - pc.x)*(pd.y - pc.y) - (pd.x - pc.x)*(pa.y - pc.y); - if (oadc <= EPSILON) { - return false; - } - return true; - } + double oadc = (pa.x - pc.x)*(pd.y - pc.y) - (pd.x - pc.x)*(pa.y - pc.y); + if (oadc <= EPSILON) { + return false; + } + return true; +} } diff --git a/poly2tri/poly2tri.h b/poly2tri/poly2tri.h index 487755e2e94305f50c464018eafcb0c3b172b495..042cb3dcb3b73858d854c1b3c0b8a58c788c515e 100644 --- a/poly2tri/poly2tri.h +++ b/poly2tri/poly2tri.h @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * http://code.google.com/p/poly2tri/ * diff --git a/poly2tri/sweep/advancing_front.cpp b/poly2tri/sweep/advancing_front.cpp index 019df4a6ebff8778614bdf7bf6b7c937aa60e29f..ebba5c0f0929f124ded75dca84102b0072042283 100644 --- a/poly2tri/sweep/advancing_front.cpp +++ b/poly2tri/sweep/advancing_front.cpp @@ -34,71 +34,71 @@ namespace p2t { AdvancingFront::AdvancingFront(Node& head, Node& tail) { - head_ = &head; - tail_ = &tail; - search_node_ = &head; + head_ = &head; + tail_ = &tail; + search_node_ = &head; } Node* AdvancingFront::LocateNode(const double& x) { - Node* node = search_node_; + Node* node = search_node_; - if (x < node->value) { - while ((node = node->prev) != NULL) { - if (x >= node->value) { - search_node_ = node; - return node; - } - } - } else { - while ((node = node->next) != NULL) { - if (x < node->value) { - search_node_ = node->prev; - return node->prev; - } - } - } - return NULL; + if (x < node->value) { + while ((node = node->prev) != NULL) { + if (x >= node->value) { + search_node_ = node; + return node; + } + } + } else { + while ((node = node->next) != NULL) { + if (x < node->value) { + search_node_ = node->prev; + return node->prev; + } + } + } + return NULL; } Node* AdvancingFront::FindSearchNode(const double& x) { - (void)x; // suppress compiler warnings "unused parameter 'x'" - // TODO: implement BST index - return search_node_; + (void)x; // suppress compiler warnings "unused parameter 'x'" + // TODO: implement BST index + return search_node_; } Node* AdvancingFront::LocatePoint(const Point* point) { - const double px = point->x; - Node* node = FindSearchNode(px); - const double nx = node->point->x; + const double px = point->x; + Node* node = FindSearchNode(px); + const double nx = node->point->x; - if (px == nx) { - if (point != node->point) { - // We might have two nodes with same x value for a short time - if (point == node->prev->point) { - node = node->prev; - } else if (point == node->next->point) { - node = node->next; - } else { - assert(0); - } - } - } else if (px < nx) { - while ((node = node->prev) != NULL) { - if (point == node->point) { - break; - } - } - } else { - while ((node = node->next) != NULL) { - if (point == node->point) - break; - } - } - if(node) search_node_ = node; - return node; + if (px == nx) { + if (point != node->point) { + // We might have two nodes with same x value for a short time + if (point == node->prev->point) { + node = node->prev; + } else if (point == node->next->point) { + node = node->next; + } else { + assert(0); + } + } + } else if (px < nx) { + while ((node = node->prev) != NULL) { + if (point == node->point) { + break; + } + } + } else { + while ((node = node->next) != NULL) { + if (point == node->point) + break; + } + } + if(node) search_node_ = node; + return node; } AdvancingFront::~AdvancingFront() diff --git a/poly2tri/sweep/advancing_front.h b/poly2tri/sweep/advancing_front.h index 4f751854cad881bf959375a83a321e023937f69a..d8a6d508c0cb550fd83c956760b182ef11e896ac 100644 --- a/poly2tri/sweep/advancing_front.h +++ b/poly2tri/sweep/advancing_front.h @@ -36,82 +36,80 @@ namespace p2t { - struct Node; - - // Advancing front node - struct Node { - Point* point; - Triangle* triangle; - - Node* next; - Node* prev; - - double value; - - Node(Point& p) : point(&p), triangle(NULL), next(NULL), prev(NULL), value(p.x) - { - } - - Node(Point& p, Triangle& t) : point(&p), triangle(&t), next(NULL), prev(NULL), value(p.x) - { - } - - }; - - // Advancing front - class AdvancingFront { - public: - - AdvancingFront(Node& head, Node& tail); - // Destructor - ~AdvancingFront(); - - Node* head(); - void set_head(Node* node); - Node* tail(); - void set_tail(Node* node); - Node* search(); - void set_search(Node* node); - - /// Locate insertion point along advancing front - Node* LocateNode(const double& x); - - Node* LocatePoint(const Point* point); - - private: - - Node* head_, *tail_, *search_node_; - - Node* FindSearchNode(const double& x); - }; - - inline Node* AdvancingFront::head() - { - return head_; - } - inline void AdvancingFront::set_head(Node* node) - { - head_ = node; - } - - inline Node* AdvancingFront::tail() - { - return tail_; - } - inline void AdvancingFront::set_tail(Node* node) - { - tail_ = node; - } - - inline Node* AdvancingFront::search() - { - return search_node_; - } - - inline void AdvancingFront::set_search(Node* node) - { - search_node_ = node; - } +struct Node; + +// Advancing front node +struct Node { + Point* point; + Triangle* triangle; + + Node* next; + Node* prev; + + double value; + + Node(Point& p) : point(&p), triangle(NULL), next(NULL), prev(NULL), value(p.x) { + } + + Node(Point& p, Triangle& t) : point(&p), triangle(&t), next(NULL), prev(NULL), value(p.x) { + } + +}; + +// Advancing front +class AdvancingFront { +public: + + AdvancingFront(Node& head, Node& tail); + // Destructor + ~AdvancingFront(); + + Node* head(); + void set_head(Node* node); + Node* tail(); + void set_tail(Node* node); + Node* search(); + void set_search(Node* node); + + /// Locate insertion point along advancing front + Node* LocateNode(const double& x); + + Node* LocatePoint(const Point* point); + +private: + + Node* head_, *tail_, *search_node_; + + Node* FindSearchNode(const double& x); +}; + +inline Node* AdvancingFront::head() +{ + return head_; +} +inline void AdvancingFront::set_head(Node* node) +{ + head_ = node; +} + +inline Node* AdvancingFront::tail() +{ + return tail_; +} +inline void AdvancingFront::set_tail(Node* node) +{ + tail_ = node; +} + +inline Node* AdvancingFront::search() +{ + return search_node_; +} + +inline void AdvancingFront::set_search(Node* node) +{ + search_node_ = node; +} } diff --git a/poly2tri/sweep/cdt.cpp b/poly2tri/sweep/cdt.cpp index f013e47e373440edf5d4ddfc2bc00fe1404d5e18..5dac53ea64f1c7ecf6d2821924d8a72e336dcadd 100644 --- a/poly2tri/sweep/cdt.cpp +++ b/poly2tri/sweep/cdt.cpp @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * http://code.google.com/p/poly2tri/ * @@ -34,38 +34,39 @@ namespace p2t { CDT::CDT(std::vector<Point*> polyline) { - sweep_context_ = new SweepContext(polyline); - sweep_ = new Sweep; + sweep_context_ = new SweepContext(polyline); + sweep_ = new Sweep; } void CDT::AddHole(std::vector<Point*> polyline) { - sweep_context_->AddHole(polyline); + sweep_context_->AddHole(polyline); } -void CDT::AddPoint(Point* point) { - sweep_context_->AddPoint(point); +void CDT::AddPoint(Point* point) +{ + sweep_context_->AddPoint(point); } void CDT::Triangulate() { - sweep_->Triangulate(*sweep_context_); + sweep_->Triangulate(*sweep_context_); } std::vector<p2t::Triangle*> CDT::GetTriangles() { - return sweep_context_->GetTriangles(); + return sweep_context_->GetTriangles(); } std::list<p2t::Triangle*> CDT::GetMap() { - return sweep_context_->GetMap(); + return sweep_context_->GetMap(); } CDT::~CDT() { - delete sweep_context_; - delete sweep_; + delete sweep_context_; + delete sweep_; } } diff --git a/poly2tri/sweep/cdt.h b/poly2tri/sweep/cdt.h index 4b835acdc2c3b9b59b3ef5abc1ea5f74dc9201c6..a16661d55d2a67b8acc6625b32d1acc50f5fbefc 100644 --- a/poly2tri/sweep/cdt.h +++ b/poly2tri/sweep/cdt.h @@ -1,4 +1,4 @@ -/* +/* * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors * http://code.google.com/p/poly2tri/ * @@ -28,7 +28,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - + #ifndef CDT_H #define CDT_H @@ -37,68 +37,67 @@ #include "sweep.h" /** - * + * * @author Mason Green <mason.green@gmail.com> * */ - + namespace p2t { - class CDT - { - public: - - /** - * Constructor - add polyline with non repeating points - * - * @param polyline - */ - CDT(std::vector<Point*> polyline); - - /** - * Destructor - clean up memory - */ - ~CDT(); - - /** - * Add a hole - * - * @param polyline - */ - void AddHole(std::vector<Point*> polyline); - - /** - * Add a steiner point - * - * @param point - */ - void AddPoint(Point* point); - - /** - * Triangulate - do this AFTER you've added the polyline, holes, and Steiner points - */ - void Triangulate(); - - /** - * Get CDT triangles - */ - std::vector<Triangle*> GetTriangles(); - - /** - * Get triangle map - */ - std::list<Triangle*> GetMap(); - - private: - - /** - * Internals - */ - - SweepContext* sweep_context_; - Sweep* sweep_; - - }; +class CDT { +public: + + /** + * Constructor - add polyline with non repeating points + * + * @param polyline + */ + CDT(std::vector<Point*> polyline); + + /** + * Destructor - clean up memory + */ + ~CDT(); + + /** + * Add a hole + * + * @param polyline + */ + void AddHole(std::vector<Point*> polyline); + + /** + * Add a steiner point + * + * @param point + */ + void AddPoint(Point* point); + + /** + * Triangulate - do this AFTER you've added the polyline, holes, and Steiner points + */ + void Triangulate(); + + /** + * Get CDT triangles + */ + std::vector<Triangle*> GetTriangles(); + + /** + * Get triangle map + */ + std::list<Triangle*> GetMap(); + +private: + + /** + * Internals + */ + + SweepContext* sweep_context_; + Sweep* sweep_; + +}; } diff --git a/poly2tri/sweep/sweep.cpp b/poly2tri/sweep/sweep.cpp index 854dfd4b6548328b35f6db9a040a2accbfcc463f..2d4f77abb16793825e3c1aa6d8c85da9e2d2f838 100644 --- a/poly2tri/sweep/sweep.cpp +++ b/poly2tri/sweep/sweep.cpp @@ -39,773 +39,778 @@ namespace p2t { // Triangulate simple polygon with holes void Sweep::Triangulate(SweepContext& tcx) { - tcx.InitTriangulation(); - tcx.CreateAdvancingFront(nodes_); - // Sweep points; build mesh - SweepPoints(tcx); - // Clean up - FinalizationPolygon(tcx); + tcx.InitTriangulation(); + tcx.CreateAdvancingFront(nodes_); + // Sweep points; build mesh + SweepPoints(tcx); + // Clean up + FinalizationPolygon(tcx); } void Sweep::SweepPoints(SweepContext& tcx) { - for (int i = 1; i < tcx.point_count(); i++) { - Point& point = *tcx.GetPoint(i); - Node* node = &PointEvent(tcx, point); - for (unsigned int i = 0; i < point.edge_list.size(); i++) { - EdgeEvent(tcx, point.edge_list[i], node); - } - } + for (int i = 1; i < tcx.point_count(); i++) { + Point& point = *tcx.GetPoint(i); + Node* node = &PointEvent(tcx, point); + for (unsigned int i = 0; i < point.edge_list.size(); i++) { + EdgeEvent(tcx, point.edge_list[i], node); + } + } } void Sweep::FinalizationPolygon(SweepContext& tcx) { - // Get an Internal triangle to start with - Triangle* t = tcx.front()->head()->next->triangle; - Point* p = tcx.front()->head()->next->point; - while (!t->GetConstrainedEdgeCW(*p)) { - t = t->NeighborCCW(*p); - } + // Get an Internal triangle to start with + Triangle* t = tcx.front()->head()->next->triangle; + Point* p = tcx.front()->head()->next->point; + while (!t->GetConstrainedEdgeCW(*p)) { + t = t->NeighborCCW(*p); + } - // Collect interior triangles constrained by edges - tcx.MeshClean(*t); + // Collect interior triangles constrained by edges + tcx.MeshClean(*t); } Node& Sweep::PointEvent(SweepContext& tcx, Point& point) { - Node& node = tcx.LocateNode(point); - Node& new_node = NewFrontTriangle(tcx, point, node); + Node& node = tcx.LocateNode(point); + Node& new_node = NewFrontTriangle(tcx, point, node); - // Only need to check +epsilon since point never have smaller - // x value than node due to how we fetch nodes from the front - if (point.x <= node.point->x + EPSILON) { - Fill(tcx, node); - } + // Only need to check +epsilon since point never have smaller + // x value than node due to how we fetch nodes from the front + if (point.x <= node.point->x + EPSILON) { + Fill(tcx, node); + } - //tcx.AddNode(new_node); + //tcx.AddNode(new_node); - FillAdvancingFront(tcx, new_node); - return new_node; + FillAdvancingFront(tcx, new_node); + return new_node; } void Sweep::EdgeEvent(SweepContext& tcx, Edge* edge, Node* node) { - tcx.edge_event.constrained_edge = edge; - tcx.edge_event.right = (edge->p->x > edge->q->x); + tcx.edge_event.constrained_edge = edge; + tcx.edge_event.right = (edge->p->x > edge->q->x); - if (IsEdgeSideOfTriangle(*node->triangle, *edge->p, *edge->q)) { - return; - } + if (IsEdgeSideOfTriangle(*node->triangle, *edge->p, *edge->q)) { + return; + } - // For now we will do all needed filling - // TODO: integrate with flip process might give some better performance - // but for now this avoid the issue with cases that needs both flips and fills - FillEdgeEvent(tcx, edge, node); - EdgeEvent(tcx, *edge->p, *edge->q, node->triangle, *edge->q); + // For now we will do all needed filling + // TODO: integrate with flip process might give some better performance + // but for now this avoid the issue with cases that needs both flips and fills + FillEdgeEvent(tcx, edge, node); + EdgeEvent(tcx, *edge->p, *edge->q, node->triangle, *edge->q); } void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point) { - if (IsEdgeSideOfTriangle(*triangle, ep, eq)) { - return; - } - - Point* p1 = triangle->PointCCW(point); - Orientation o1 = Orient2d(eq, *p1, ep); - if (o1 == COLLINEAR) { - if( triangle->Contains(&eq, p1)) { - triangle->MarkConstrainedEdge(&eq, p1 ); - // We are modifying the constraint maybe it would be better to - // not change the given constraint and just keep a variable for the new constraint - tcx.edge_event.constrained_edge->q = p1; - triangle = &triangle->NeighborAcross(point); - EdgeEvent( tcx, ep, *p1, triangle, *p1 ); - } else { - std::runtime_error("EdgeEvent - collinear points not supported"); - assert(0); - } - return; - } - - Point* p2 = triangle->PointCW(point); - Orientation o2 = Orient2d(eq, *p2, ep); - if (o2 == COLLINEAR) { - if( triangle->Contains(&eq, p2)) { - triangle->MarkConstrainedEdge(&eq, p2 ); - // We are modifying the constraint maybe it would be better to - // not change the given constraint and just keep a variable for the new constraint - tcx.edge_event.constrained_edge->q = p2; - triangle = &triangle->NeighborAcross(point); - EdgeEvent( tcx, ep, *p2, triangle, *p2 ); - } else { - std::runtime_error("EdgeEvent - collinear points not supported"); - assert(0); - } - return; - } - - if (o1 == o2) { - // Need to decide if we are rotating CW or CCW to get to a triangle - // that will cross edge - if (o1 == CW) { - triangle = triangle->NeighborCCW(point); - } else{ - triangle = triangle->NeighborCW(point); - } - EdgeEvent(tcx, ep, eq, triangle, point); - } else { - // This triangle crosses constraint so lets flippin start! - FlipEdgeEvent(tcx, ep, eq, triangle, point); - } + if (IsEdgeSideOfTriangle(*triangle, ep, eq)) { + return; + } + + Point* p1 = triangle->PointCCW(point); + Orientation o1 = Orient2d(eq, *p1, ep); + if (o1 == COLLINEAR) { + if( triangle->Contains(&eq, p1)) { + triangle->MarkConstrainedEdge(&eq, p1 ); + // We are modifying the constraint maybe it would be better to + // not change the given constraint and just keep a variable for the new constraint + tcx.edge_event.constrained_edge->q = p1; + triangle = &triangle->NeighborAcross(point); + EdgeEvent( tcx, ep, *p1, triangle, *p1 ); + } else { + std::runtime_error("EdgeEvent - collinear points not supported"); + assert(0); + } + return; + } + + Point* p2 = triangle->PointCW(point); + Orientation o2 = Orient2d(eq, *p2, ep); + if (o2 == COLLINEAR) { + if( triangle->Contains(&eq, p2)) { + triangle->MarkConstrainedEdge(&eq, p2 ); + // We are modifying the constraint maybe it would be better to + // not change the given constraint and just keep a variable for the new constraint + tcx.edge_event.constrained_edge->q = p2; + triangle = &triangle->NeighborAcross(point); + EdgeEvent( tcx, ep, *p2, triangle, *p2 ); + } else { + std::runtime_error("EdgeEvent - collinear points not supported"); + assert(0); + } + return; + } + + if (o1 == o2) { + // Need to decide if we are rotating CW or CCW to get to a triangle + // that will cross edge + if (o1 == CW) { + triangle = triangle->NeighborCCW(point); + } else { + triangle = triangle->NeighborCW(point); + } + EdgeEvent(tcx, ep, eq, triangle, point); + } else { + // This triangle crosses constraint so lets flippin start! + FlipEdgeEvent(tcx, ep, eq, triangle, point); + } } bool Sweep::IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq) { - int index = triangle.EdgeIndex(&ep, &eq); + int index = triangle.EdgeIndex(&ep, &eq); - if (index != -1) { - triangle.MarkConstrainedEdge(index); - Triangle* t = triangle.GetNeighbor(index); - if (t) { - t->MarkConstrainedEdge(&ep, &eq); - } - return true; - } - return false; + if (index != -1) { + triangle.MarkConstrainedEdge(index); + Triangle* t = triangle.GetNeighbor(index); + if (t) { + t->MarkConstrainedEdge(&ep, &eq); + } + return true; + } + return false; } Node& Sweep::NewFrontTriangle(SweepContext& tcx, Point& point, Node& node) { - Triangle* triangle = new Triangle(point, *node.point, *node.next->point); + Triangle* triangle = new Triangle(point, *node.point, *node.next->point); - triangle->MarkNeighbor(*node.triangle); - tcx.AddToMap(triangle); + triangle->MarkNeighbor(*node.triangle); + tcx.AddToMap(triangle); - Node* new_node = new Node(point); - nodes_.push_back(new_node); + Node* new_node = new Node(point); + nodes_.push_back(new_node); - new_node->next = node.next; - new_node->prev = &node; - node.next->prev = new_node; - node.next = new_node; + new_node->next = node.next; + new_node->prev = &node; + node.next->prev = new_node; + node.next = new_node; - if (!Legalize(tcx, *triangle)) { - tcx.MapTriangleToNodes(*triangle); - } + if (!Legalize(tcx, *triangle)) { + tcx.MapTriangleToNodes(*triangle); + } - return *new_node; + return *new_node; } void Sweep::Fill(SweepContext& tcx, Node& node) { - Triangle* triangle = new Triangle(*node.prev->point, *node.point, *node.next->point); + Triangle* triangle = new Triangle(*node.prev->point, *node.point, *node.next->point); - // TODO: should copy the constrained_edge value from neighbor triangles - // for now constrained_edge values are copied during the legalize - triangle->MarkNeighbor(*node.prev->triangle); - triangle->MarkNeighbor(*node.triangle); + // TODO: should copy the constrained_edge value from neighbor triangles + // for now constrained_edge values are copied during the legalize + triangle->MarkNeighbor(*node.prev->triangle); + triangle->MarkNeighbor(*node.triangle); - tcx.AddToMap(triangle); + tcx.AddToMap(triangle); - // Update the advancing front - node.prev->next = node.next; - node.next->prev = node.prev; + // Update the advancing front + node.prev->next = node.next; + node.next->prev = node.prev; - // If it was legalized the triangle has already been mapped - if (!Legalize(tcx, *triangle)) { - tcx.MapTriangleToNodes(*triangle); - } + // If it was legalized the triangle has already been mapped + if (!Legalize(tcx, *triangle)) { + tcx.MapTriangleToNodes(*triangle); + } } void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n) -{ +{ - // Fill right holes - Node* node = n.next; + // Fill right holes + Node* node = n.next; - while (node->next) { - // if HoleAngle exceeds 90 degrees then break. - if (LargeHole_DontFill(node)) break; - Fill(tcx, *node); - node = node->next; - } + while (node->next) { + // if HoleAngle exceeds 90 degrees then break. + if (LargeHole_DontFill(node)) break; + Fill(tcx, *node); + node = node->next; + } - // Fill left holes - node = n.prev; + // Fill left holes + node = n.prev; - while (node->prev) { - // if HoleAngle exceeds 90 degrees then break. - if (LargeHole_DontFill(node)) break; - Fill(tcx, *node); - node = node->prev; - } + while (node->prev) { + // if HoleAngle exceeds 90 degrees then break. + if (LargeHole_DontFill(node)) break; + Fill(tcx, *node); + node = node->prev; + } - // Fill right basins - if (n.next && n.next->next) { - double angle = BasinAngle(n); - if (angle < PI_3div4) { - FillBasin(tcx, n); - } - } + // Fill right basins + if (n.next && n.next->next) { + double angle = BasinAngle(n); + if (angle < PI_3div4) { + FillBasin(tcx, n); + } + } } // True if HoleAngle exceeds 90 degrees. -bool Sweep::LargeHole_DontFill(Node* node) { - - Node* nextNode = node->next; - Node* prevNode = node->prev; - if (!AngleExceeds90Degrees(node->point, nextNode->point, prevNode->point)) - return false; - - // Check additional points on front. - Node* next2Node = nextNode->next; - // "..Plus.." because only want angles on same side as point being added. - if ((next2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, next2Node->point, prevNode->point)) - return false; - - Node* prev2Node = prevNode->prev; - // "..Plus.." because only want angles on same side as point being added. - if ((prev2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, nextNode->point, prev2Node->point)) - return false; - - return true; -} - -bool Sweep::AngleExceeds90Degrees(Point* origin, Point* pa, Point* pb) { - double angle = Angle(*origin, *pa, *pb); - bool exceeds90Degrees = ((angle > PI_div2) || (angle < -PI_div2)); - return exceeds90Degrees; -} - -bool Sweep::AngleExceedsPlus90DegreesOrIsNegative(Point* origin, Point* pa, Point* pb) { - double angle = Angle(*origin, *pa, *pb); - bool exceedsPlus90DegreesOrIsNegative = (angle > PI_div2) || (angle < 0); - return exceedsPlus90DegreesOrIsNegative; -} - -double Sweep::Angle(Point& origin, Point& pa, Point& pb) { - /* Complex plane - * ab = cosA +i*sinA - * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx) - * atan2(y,x) computes the principal value of the argument function - * applied to the complex number x+iy - * Where x = ax*bx + ay*by - * y = ax*by - ay*bx - */ - double px = origin.x; - double py = origin.y; - double ax = pa.x- px; - double ay = pa.y - py; - double bx = pb.x - px; - double by = pb.y - py; - double x = ax * by - ay * bx; - double y = ax * bx + ay * by; - double angle = atan2(x, y); - return angle; +bool Sweep::LargeHole_DontFill(Node* node) +{ + + Node* nextNode = node->next; + Node* prevNode = node->prev; + if (!AngleExceeds90Degrees(node->point, nextNode->point, prevNode->point)) + return false; + + // Check additional points on front. + Node* next2Node = nextNode->next; + // "..Plus.." because only want angles on same side as point being added. + if ((next2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, next2Node->point, prevNode->point)) + return false; + + Node* prev2Node = prevNode->prev; + // "..Plus.." because only want angles on same side as point being added. + if ((prev2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, nextNode->point, prev2Node->point)) + return false; + + return true; +} + +bool Sweep::AngleExceeds90Degrees(Point* origin, Point* pa, Point* pb) +{ + double angle = Angle(*origin, *pa, *pb); + bool exceeds90Degrees = ((angle > PI_div2) || (angle < -PI_div2)); + return exceeds90Degrees; +} + +bool Sweep::AngleExceedsPlus90DegreesOrIsNegative(Point* origin, Point* pa, Point* pb) +{ + double angle = Angle(*origin, *pa, *pb); + bool exceedsPlus90DegreesOrIsNegative = (angle > PI_div2) || (angle < 0); + return exceedsPlus90DegreesOrIsNegative; +} + +double Sweep::Angle(Point& origin, Point& pa, Point& pb) +{ + /* Complex plane + * ab = cosA +i*sinA + * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx) + * atan2(y,x) computes the principal value of the argument function + * applied to the complex number x+iy + * Where x = ax*bx + ay*by + * y = ax*by - ay*bx + */ + double px = origin.x; + double py = origin.y; + double ax = pa.x- px; + double ay = pa.y - py; + double bx = pb.x - px; + double by = pb.y - py; + double x = ax * by - ay * bx; + double y = ax * bx + ay * by; + double angle = atan2(x, y); + return angle; } double Sweep::BasinAngle(Node& node) { - double ax = node.point->x - node.next->next->point->x; - double ay = node.point->y - node.next->next->point->y; - return atan2(ay, ax); + double ax = node.point->x - node.next->next->point->x; + double ay = node.point->y - node.next->next->point->y; + return atan2(ay, ax); } double Sweep::HoleAngle(Node& node) { - /* Complex plane - * ab = cosA +i*sinA - * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx) - * atan2(y,x) computes the principal value of the argument function - * applied to the complex number x+iy - * Where x = ax*bx + ay*by - * y = ax*by - ay*bx - */ - double ax = node.next->point->x - node.point->x; - double ay = node.next->point->y - node.point->y; - double bx = node.prev->point->x - node.point->x; - double by = node.prev->point->y - node.point->y; - return atan2(ax * by - ay * bx, ax * bx + ay * by); + /* Complex plane + * ab = cosA +i*sinA + * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx) + * atan2(y,x) computes the principal value of the argument function + * applied to the complex number x+iy + * Where x = ax*bx + ay*by + * y = ax*by - ay*bx + */ + double ax = node.next->point->x - node.point->x; + double ay = node.next->point->y - node.point->y; + double bx = node.prev->point->x - node.point->x; + double by = node.prev->point->y - node.point->y; + return atan2(ax * by - ay * bx, ax * bx + ay * by); } bool Sweep::Legalize(SweepContext& tcx, Triangle& t) { - // To legalize a triangle we start by finding if any of the three edges - // violate the Delaunay condition - for (int i = 0; i < 3; i++) { - if (t.delaunay_edge[i]) - continue; - - Triangle* ot = t.GetNeighbor(i); - - if (ot) { - Point* p = t.GetPoint(i); - Point* op = ot->OppositePoint(t, *p); - int oi = ot->Index(op); - - // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization) - // then we should not try to legalize - if (ot->constrained_edge[oi] || ot->delaunay_edge[oi]) { - t.constrained_edge[i] = ot->constrained_edge[oi]; - continue; - } - - bool inside = Incircle(*p, *t.PointCCW(*p), *t.PointCW(*p), *op); - - if (inside) { - // Lets mark this shared edge as Delaunay - t.delaunay_edge[i] = true; - ot->delaunay_edge[oi] = true; - - // Lets rotate shared edge one vertex CW to legalize it - RotateTrianglePair(t, *p, *ot, *op); - - // We now got one valid Delaunay Edge shared by two triangles - // This gives us 4 new edges to check for Delaunay - - // Make sure that triangle to node mapping is done only one time for a specific triangle - bool not_legalized = !Legalize(tcx, t); - if (not_legalized) { - tcx.MapTriangleToNodes(t); - } - - not_legalized = !Legalize(tcx, *ot); - if (not_legalized) - tcx.MapTriangleToNodes(*ot); - - // Reset the Delaunay edges, since they only are valid Delaunay edges - // until we add a new triangle or point. - // XXX: need to think about this. Can these edges be tried after we - // return to previous recursive level? - t.delaunay_edge[i] = false; - ot->delaunay_edge[oi] = false; - - // If triangle have been legalized no need to check the other edges since - // the recursive legalization will handles those so we can end here. - return true; - } - } - } - return false; + // To legalize a triangle we start by finding if any of the three edges + // violate the Delaunay condition + for (int i = 0; i < 3; i++) { + if (t.delaunay_edge[i]) + continue; + + Triangle* ot = t.GetNeighbor(i); + + if (ot) { + Point* p = t.GetPoint(i); + Point* op = ot->OppositePoint(t, *p); + int oi = ot->Index(op); + + // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization) + // then we should not try to legalize + if (ot->constrained_edge[oi] || ot->delaunay_edge[oi]) { + t.constrained_edge[i] = ot->constrained_edge[oi]; + continue; + } + + bool inside = Incircle(*p, *t.PointCCW(*p), *t.PointCW(*p), *op); + + if (inside) { + // Lets mark this shared edge as Delaunay + t.delaunay_edge[i] = true; + ot->delaunay_edge[oi] = true; + + // Lets rotate shared edge one vertex CW to legalize it + RotateTrianglePair(t, *p, *ot, *op); + + // We now got one valid Delaunay Edge shared by two triangles + // This gives us 4 new edges to check for Delaunay + + // Make sure that triangle to node mapping is done only one time for a specific triangle + bool not_legalized = !Legalize(tcx, t); + if (not_legalized) { + tcx.MapTriangleToNodes(t); + } + + not_legalized = !Legalize(tcx, *ot); + if (not_legalized) + tcx.MapTriangleToNodes(*ot); + + // Reset the Delaunay edges, since they only are valid Delaunay edges + // until we add a new triangle or point. + // XXX: need to think about this. Can these edges be tried after we + // return to previous recursive level? + t.delaunay_edge[i] = false; + ot->delaunay_edge[oi] = false; + + // If triangle have been legalized no need to check the other edges since + // the recursive legalization will handles those so we can end here. + return true; + } + } + } + return false; } bool Sweep::Incircle(Point& pa, Point& pb, Point& pc, Point& pd) { - double adx = pa.x - pd.x; - double ady = pa.y - pd.y; - double bdx = pb.x - pd.x; - double bdy = pb.y - pd.y; + double adx = pa.x - pd.x; + double ady = pa.y - pd.y; + double bdx = pb.x - pd.x; + double bdy = pb.y - pd.y; - double adxbdy = adx * bdy; - double bdxady = bdx * ady; - double oabd = adxbdy - bdxady; + double adxbdy = adx * bdy; + double bdxady = bdx * ady; + double oabd = adxbdy - bdxady; - if (oabd <= 0) - return false; + if (oabd <= 0) + return false; - double cdx = pc.x - pd.x; - double cdy = pc.y - pd.y; + double cdx = pc.x - pd.x; + double cdy = pc.y - pd.y; - double cdxady = cdx * ady; - double adxcdy = adx * cdy; - double ocad = cdxady - adxcdy; + double cdxady = cdx * ady; + double adxcdy = adx * cdy; + double ocad = cdxady - adxcdy; - if (ocad <= 0) - return false; + if (ocad <= 0) + return false; - double bdxcdy = bdx * cdy; - double cdxbdy = cdx * bdy; + double bdxcdy = bdx * cdy; + double cdxbdy = cdx * bdy; - double alift = adx * adx + ady * ady; - double blift = bdx * bdx + bdy * bdy; - double clift = cdx * cdx + cdy * cdy; + double alift = adx * adx + ady * ady; + double blift = bdx * bdx + bdy * bdy; + double clift = cdx * cdx + cdy * cdy; - double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd; + double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd; - return det > 0; + return det > 0; } void Sweep::RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op) { - Triangle* n1, *n2, *n3, *n4; - n1 = t.NeighborCCW(p); - n2 = t.NeighborCW(p); - n3 = ot.NeighborCCW(op); - n4 = ot.NeighborCW(op); - - bool ce1, ce2, ce3, ce4; - ce1 = t.GetConstrainedEdgeCCW(p); - ce2 = t.GetConstrainedEdgeCW(p); - ce3 = ot.GetConstrainedEdgeCCW(op); - ce4 = ot.GetConstrainedEdgeCW(op); - - bool de1, de2, de3, de4; - de1 = t.GetDelunayEdgeCCW(p); - de2 = t.GetDelunayEdgeCW(p); - de3 = ot.GetDelunayEdgeCCW(op); - de4 = ot.GetDelunayEdgeCW(op); - - t.Legalize(p, op); - ot.Legalize(op, p); - - // Remap delaunay_edge - ot.SetDelunayEdgeCCW(p, de1); - t.SetDelunayEdgeCW(p, de2); - t.SetDelunayEdgeCCW(op, de3); - ot.SetDelunayEdgeCW(op, de4); - - // Remap constrained_edge - ot.SetConstrainedEdgeCCW(p, ce1); - t.SetConstrainedEdgeCW(p, ce2); - t.SetConstrainedEdgeCCW(op, ce3); - ot.SetConstrainedEdgeCW(op, ce4); - - // Remap neighbors - // XXX: might optimize the markNeighbor by keeping track of - // what side should be assigned to what neighbor after the - // rotation. Now mark neighbor does lots of testing to find - // the right side. - t.ClearNeighbors(); - ot.ClearNeighbors(); - if (n1) ot.MarkNeighbor(*n1); - if (n2) t.MarkNeighbor(*n2); - if (n3) t.MarkNeighbor(*n3); - if (n4) ot.MarkNeighbor(*n4); - t.MarkNeighbor(ot); + Triangle* n1, *n2, *n3, *n4; + n1 = t.NeighborCCW(p); + n2 = t.NeighborCW(p); + n3 = ot.NeighborCCW(op); + n4 = ot.NeighborCW(op); + + bool ce1, ce2, ce3, ce4; + ce1 = t.GetConstrainedEdgeCCW(p); + ce2 = t.GetConstrainedEdgeCW(p); + ce3 = ot.GetConstrainedEdgeCCW(op); + ce4 = ot.GetConstrainedEdgeCW(op); + + bool de1, de2, de3, de4; + de1 = t.GetDelunayEdgeCCW(p); + de2 = t.GetDelunayEdgeCW(p); + de3 = ot.GetDelunayEdgeCCW(op); + de4 = ot.GetDelunayEdgeCW(op); + + t.Legalize(p, op); + ot.Legalize(op, p); + + // Remap delaunay_edge + ot.SetDelunayEdgeCCW(p, de1); + t.SetDelunayEdgeCW(p, de2); + t.SetDelunayEdgeCCW(op, de3); + ot.SetDelunayEdgeCW(op, de4); + + // Remap constrained_edge + ot.SetConstrainedEdgeCCW(p, ce1); + t.SetConstrainedEdgeCW(p, ce2); + t.SetConstrainedEdgeCCW(op, ce3); + ot.SetConstrainedEdgeCW(op, ce4); + + // Remap neighbors + // XXX: might optimize the markNeighbor by keeping track of + // what side should be assigned to what neighbor after the + // rotation. Now mark neighbor does lots of testing to find + // the right side. + t.ClearNeighbors(); + ot.ClearNeighbors(); + if (n1) ot.MarkNeighbor(*n1); + if (n2) t.MarkNeighbor(*n2); + if (n3) t.MarkNeighbor(*n3); + if (n4) ot.MarkNeighbor(*n4); + t.MarkNeighbor(ot); } void Sweep::FillBasin(SweepContext& tcx, Node& node) { - if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { - tcx.basin.left_node = node.next->next; - } else { - tcx.basin.left_node = node.next; - } - - // Find the bottom and right node - tcx.basin.bottom_node = tcx.basin.left_node; - while (tcx.basin.bottom_node->next - && tcx.basin.bottom_node->point->y >= tcx.basin.bottom_node->next->point->y) { - tcx.basin.bottom_node = tcx.basin.bottom_node->next; - } - if (tcx.basin.bottom_node == tcx.basin.left_node) { - // No valid basin - return; - } - - tcx.basin.right_node = tcx.basin.bottom_node; - while (tcx.basin.right_node->next - && tcx.basin.right_node->point->y < tcx.basin.right_node->next->point->y) { - tcx.basin.right_node = tcx.basin.right_node->next; - } - if (tcx.basin.right_node == tcx.basin.bottom_node) { - // No valid basins - return; - } - - tcx.basin.width = tcx.basin.right_node->point->x - tcx.basin.left_node->point->x; - tcx.basin.left_highest = tcx.basin.left_node->point->y > tcx.basin.right_node->point->y; - - FillBasinReq(tcx, tcx.basin.bottom_node); + if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { + tcx.basin.left_node = node.next->next; + } else { + tcx.basin.left_node = node.next; + } + + // Find the bottom and right node + tcx.basin.bottom_node = tcx.basin.left_node; + while (tcx.basin.bottom_node->next + && tcx.basin.bottom_node->point->y >= tcx.basin.bottom_node->next->point->y) { + tcx.basin.bottom_node = tcx.basin.bottom_node->next; + } + if (tcx.basin.bottom_node == tcx.basin.left_node) { + // No valid basin + return; + } + + tcx.basin.right_node = tcx.basin.bottom_node; + while (tcx.basin.right_node->next + && tcx.basin.right_node->point->y < tcx.basin.right_node->next->point->y) { + tcx.basin.right_node = tcx.basin.right_node->next; + } + if (tcx.basin.right_node == tcx.basin.bottom_node) { + // No valid basins + return; + } + + tcx.basin.width = tcx.basin.right_node->point->x - tcx.basin.left_node->point->x; + tcx.basin.left_highest = tcx.basin.left_node->point->y > tcx.basin.right_node->point->y; + + FillBasinReq(tcx, tcx.basin.bottom_node); } void Sweep::FillBasinReq(SweepContext& tcx, Node* node) { - // if shallow stop filling - if (IsShallow(tcx, *node)) { - return; - } - - Fill(tcx, *node); - - if (node->prev == tcx.basin.left_node && node->next == tcx.basin.right_node) { - return; - } else if (node->prev == tcx.basin.left_node) { - Orientation o = Orient2d(*node->point, *node->next->point, *node->next->next->point); - if (o == CW) { - return; - } - node = node->next; - } else if (node->next == tcx.basin.right_node) { - Orientation o = Orient2d(*node->point, *node->prev->point, *node->prev->prev->point); - if (o == CCW) { - return; - } - node = node->prev; - } else { - // Continue with the neighbor node with lowest Y value - if (node->prev->point->y < node->next->point->y) { - node = node->prev; - } else { - node = node->next; - } - } - - FillBasinReq(tcx, node); + // if shallow stop filling + if (IsShallow(tcx, *node)) { + return; + } + + Fill(tcx, *node); + + if (node->prev == tcx.basin.left_node && node->next == tcx.basin.right_node) { + return; + } else if (node->prev == tcx.basin.left_node) { + Orientation o = Orient2d(*node->point, *node->next->point, *node->next->next->point); + if (o == CW) { + return; + } + node = node->next; + } else if (node->next == tcx.basin.right_node) { + Orientation o = Orient2d(*node->point, *node->prev->point, *node->prev->prev->point); + if (o == CCW) { + return; + } + node = node->prev; + } else { + // Continue with the neighbor node with lowest Y value + if (node->prev->point->y < node->next->point->y) { + node = node->prev; + } else { + node = node->next; + } + } + + FillBasinReq(tcx, node); } bool Sweep::IsShallow(SweepContext& tcx, Node& node) { - double height; + double height; - if (tcx.basin.left_highest) { - height = tcx.basin.left_node->point->y - node.point->y; - } else { - height = tcx.basin.right_node->point->y - node.point->y; - } + if (tcx.basin.left_highest) { + height = tcx.basin.left_node->point->y - node.point->y; + } else { + height = tcx.basin.right_node->point->y - node.point->y; + } - // if shallow stop filling - if (tcx.basin.width > height) { - return true; - } - return false; + // if shallow stop filling + if (tcx.basin.width > height) { + return true; + } + return false; } void Sweep::FillEdgeEvent(SweepContext& tcx, Edge* edge, Node* node) { - if (tcx.edge_event.right) { - FillRightAboveEdgeEvent(tcx, edge, node); - } else { - FillLeftAboveEdgeEvent(tcx, edge, node); - } + if (tcx.edge_event.right) { + FillRightAboveEdgeEvent(tcx, edge, node); + } else { + FillLeftAboveEdgeEvent(tcx, edge, node); + } } void Sweep::FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node) { - while (node->next->point->x < edge->p->x) { - // Check if next node is below the edge - if (Orient2d(*edge->q, *node->next->point, *edge->p) == CCW) { - FillRightBelowEdgeEvent(tcx, edge, *node); - } else { - node = node->next; - } - } + while (node->next->point->x < edge->p->x) { + // Check if next node is below the edge + if (Orient2d(*edge->q, *node->next->point, *edge->p) == CCW) { + FillRightBelowEdgeEvent(tcx, edge, *node); + } else { + node = node->next; + } + } } void Sweep::FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - if (node.point->x < edge->p->x) { - if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { - // Concave - FillRightConcaveEdgeEvent(tcx, edge, node); - } else{ - // Convex - FillRightConvexEdgeEvent(tcx, edge, node); - // Retry this one - FillRightBelowEdgeEvent(tcx, edge, node); - } - } + if (node.point->x < edge->p->x) { + if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { + // Concave + FillRightConcaveEdgeEvent(tcx, edge, node); + } else { + // Convex + FillRightConvexEdgeEvent(tcx, edge, node); + // Retry this one + FillRightBelowEdgeEvent(tcx, edge, node); + } + } } void Sweep::FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - Fill(tcx, *node.next); - if (node.next->point != edge->p) { - // Next above or below edge? - if (Orient2d(*edge->q, *node.next->point, *edge->p) == CCW) { - // Below - if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { - // Next is concave - FillRightConcaveEdgeEvent(tcx, edge, node); - } else { - // Next is convex - } - } - } + Fill(tcx, *node.next); + if (node.next->point != edge->p) { + // Next above or below edge? + if (Orient2d(*edge->q, *node.next->point, *edge->p) == CCW) { + // Below + if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) { + // Next is concave + FillRightConcaveEdgeEvent(tcx, edge, node); + } else { + // Next is convex + } + } + } } void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - // Next concave or convex? - if (Orient2d(*node.next->point, *node.next->next->point, *node.next->next->next->point) == CCW) { - // Concave - FillRightConcaveEdgeEvent(tcx, edge, *node.next); - } else{ - // Convex - // Next above or below edge? - if (Orient2d(*edge->q, *node.next->next->point, *edge->p) == CCW) { - // Below - FillRightConvexEdgeEvent(tcx, edge, *node.next); - } else{ - // Above - } - } + // Next concave or convex? + if (Orient2d(*node.next->point, *node.next->next->point, *node.next->next->next->point) == CCW) { + // Concave + FillRightConcaveEdgeEvent(tcx, edge, *node.next); + } else { + // Convex + // Next above or below edge? + if (Orient2d(*edge->q, *node.next->next->point, *edge->p) == CCW) { + // Below + FillRightConvexEdgeEvent(tcx, edge, *node.next); + } else { + // Above + } + } } void Sweep::FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node) { - while (node->prev->point->x > edge->p->x) { - // Check if next node is below the edge - if (Orient2d(*edge->q, *node->prev->point, *edge->p) == CW) { - FillLeftBelowEdgeEvent(tcx, edge, *node); - } else { - node = node->prev; - } - } + while (node->prev->point->x > edge->p->x) { + // Check if next node is below the edge + if (Orient2d(*edge->q, *node->prev->point, *edge->p) == CW) { + FillLeftBelowEdgeEvent(tcx, edge, *node); + } else { + node = node->prev; + } + } } void Sweep::FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - if (node.point->x > edge->p->x) { - if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { - // Concave - FillLeftConcaveEdgeEvent(tcx, edge, node); - } else { - // Convex - FillLeftConvexEdgeEvent(tcx, edge, node); - // Retry this one - FillLeftBelowEdgeEvent(tcx, edge, node); - } - } + if (node.point->x > edge->p->x) { + if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { + // Concave + FillLeftConcaveEdgeEvent(tcx, edge, node); + } else { + // Convex + FillLeftConvexEdgeEvent(tcx, edge, node); + // Retry this one + FillLeftBelowEdgeEvent(tcx, edge, node); + } + } } void Sweep::FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - // Next concave or convex? - if (Orient2d(*node.prev->point, *node.prev->prev->point, *node.prev->prev->prev->point) == CW) { - // Concave - FillLeftConcaveEdgeEvent(tcx, edge, *node.prev); - } else{ - // Convex - // Next above or below edge? - if (Orient2d(*edge->q, *node.prev->prev->point, *edge->p) == CW) { - // Below - FillLeftConvexEdgeEvent(tcx, edge, *node.prev); - } else{ - // Above - } - } + // Next concave or convex? + if (Orient2d(*node.prev->point, *node.prev->prev->point, *node.prev->prev->prev->point) == CW) { + // Concave + FillLeftConcaveEdgeEvent(tcx, edge, *node.prev); + } else { + // Convex + // Next above or below edge? + if (Orient2d(*edge->q, *node.prev->prev->point, *edge->p) == CW) { + // Below + FillLeftConvexEdgeEvent(tcx, edge, *node.prev); + } else { + // Above + } + } } void Sweep::FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node) { - Fill(tcx, *node.prev); - if (node.prev->point != edge->p) { - // Next above or below edge? - if (Orient2d(*edge->q, *node.prev->point, *edge->p) == CW) { - // Below - if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { - // Next is concave - FillLeftConcaveEdgeEvent(tcx, edge, node); - } else{ - // Next is convex - } - } - } + Fill(tcx, *node.prev); + if (node.prev->point != edge->p) { + // Next above or below edge? + if (Orient2d(*edge->q, *node.prev->point, *edge->p) == CW) { + // Below + if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) { + // Next is concave + FillLeftConcaveEdgeEvent(tcx, edge, node); + } else { + // Next is convex + } + } + } } void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p) { - Triangle& ot = t->NeighborAcross(p); - Point& op = *ot.OppositePoint(*t, p); - - if (&ot == NULL) { - // If we want to integrate the fillEdgeEvent do it here - // With current implementation we should never get here - //throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle"); - assert(0); - } - - if (InScanArea(p, *t->PointCCW(p), *t->PointCW(p), op)) { - // Lets rotate shared edge one vertex CW - RotateTrianglePair(*t, p, ot, op); - tcx.MapTriangleToNodes(*t); - tcx.MapTriangleToNodes(ot); - - if (p == eq && op == ep) { - if (eq == *tcx.edge_event.constrained_edge->q && ep == *tcx.edge_event.constrained_edge->p) { - t->MarkConstrainedEdge(&ep, &eq); - ot.MarkConstrainedEdge(&ep, &eq); - Legalize(tcx, *t); - Legalize(tcx, ot); - } else { - // XXX: I think one of the triangles should be legalized here? - } - } else { - Orientation o = Orient2d(eq, op, ep); - t = &NextFlipTriangle(tcx, (int)o, *t, ot, p, op); - FlipEdgeEvent(tcx, ep, eq, t, p); - } - } else { - Point& newP = NextFlipPoint(ep, eq, ot, op); - FlipScanEdgeEvent(tcx, ep, eq, *t, ot, newP); - EdgeEvent(tcx, ep, eq, t, p); - } + Triangle& ot = t->NeighborAcross(p); + Point& op = *ot.OppositePoint(*t, p); + + if (&ot == NULL) { + // If we want to integrate the fillEdgeEvent do it here + // With current implementation we should never get here + //throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle"); + assert(0); + } + + if (InScanArea(p, *t->PointCCW(p), *t->PointCW(p), op)) { + // Lets rotate shared edge one vertex CW + RotateTrianglePair(*t, p, ot, op); + tcx.MapTriangleToNodes(*t); + tcx.MapTriangleToNodes(ot); + + if (p == eq && op == ep) { + if (eq == *tcx.edge_event.constrained_edge->q && ep == *tcx.edge_event.constrained_edge->p) { + t->MarkConstrainedEdge(&ep, &eq); + ot.MarkConstrainedEdge(&ep, &eq); + Legalize(tcx, *t); + Legalize(tcx, ot); + } else { + // XXX: I think one of the triangles should be legalized here? + } + } else { + Orientation o = Orient2d(eq, op, ep); + t = &NextFlipTriangle(tcx, (int)o, *t, ot, p, op); + FlipEdgeEvent(tcx, ep, eq, t, p); + } + } else { + Point& newP = NextFlipPoint(ep, eq, ot, op); + FlipScanEdgeEvent(tcx, ep, eq, *t, ot, newP); + EdgeEvent(tcx, ep, eq, t, p); + } } Triangle& Sweep::NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op) { - if (o == CCW) { - // ot is not crossing edge after flip - int edge_index = ot.EdgeIndex(&p, &op); - ot.delaunay_edge[edge_index] = true; - Legalize(tcx, ot); - ot.ClearDelunayEdges(); - return t; - } + if (o == CCW) { + // ot is not crossing edge after flip + int edge_index = ot.EdgeIndex(&p, &op); + ot.delaunay_edge[edge_index] = true; + Legalize(tcx, ot); + ot.ClearDelunayEdges(); + return t; + } - // t is not crossing edge after flip - int edge_index = t.EdgeIndex(&p, &op); + // t is not crossing edge after flip + int edge_index = t.EdgeIndex(&p, &op); - t.delaunay_edge[edge_index] = true; - Legalize(tcx, t); - t.ClearDelunayEdges(); - return ot; + t.delaunay_edge[edge_index] = true; + Legalize(tcx, t); + t.ClearDelunayEdges(); + return ot; } Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op) { - Orientation o2d = Orient2d(eq, op, ep); - if (o2d == CW) { - // Right - return *ot.PointCCW(op); - } else if (o2d == CCW) { - // Left - return *ot.PointCW(op); - } else{ - //throw new RuntimeException("[Unsupported] Opposing point on constrained edge"); - assert(0); - } + Orientation o2d = Orient2d(eq, op, ep); + if (o2d == CW) { + // Right + return *ot.PointCCW(op); + } else if (o2d == CCW) { + // Left + return *ot.PointCW(op); + } else { + //throw new RuntimeException("[Unsupported] Opposing point on constrained edge"); + assert(0); + } } void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, - Triangle& t, Point& p) -{ - Triangle& ot = t.NeighborAcross(p); - Point& op = *ot.OppositePoint(t, p); - - if (&t.NeighborAcross(p) == NULL) { - // If we want to integrate the fillEdgeEvent do it here - // With current implementation we should never get here - //throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle"); - assert(0); - } - - if (InScanArea(eq, *flip_triangle.PointCCW(eq), *flip_triangle.PointCW(eq), op)) { - // flip with new edge op->eq - FlipEdgeEvent(tcx, eq, op, &ot, op); - // TODO: Actually I just figured out that it should be possible to - // improve this by getting the next ot and op before the the above - // flip and continue the flipScanEdgeEvent here - // set new ot and op here and loop back to inScanArea test - // also need to set a new flip_triangle first - // Turns out at first glance that this is somewhat complicated - // so it will have to wait. - } else{ - Point& newP = NextFlipPoint(ep, eq, ot, op); - FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, ot, newP); - } -} - -Sweep::~Sweep() { - // Clean up memory - for(unsigned int i = 0; i < nodes_.size(); i++) { - delete nodes_[i]; - } - + Triangle& t, Point& p) +{ + Triangle& ot = t.NeighborAcross(p); + Point& op = *ot.OppositePoint(t, p); + + if (&t.NeighborAcross(p) == NULL) { + // If we want to integrate the fillEdgeEvent do it here + // With current implementation we should never get here + //throw new RuntimeException( "[BUG:FIXME] FLIP failed due to missing triangle"); + assert(0); + } + + if (InScanArea(eq, *flip_triangle.PointCCW(eq), *flip_triangle.PointCW(eq), op)) { + // flip with new edge op->eq + FlipEdgeEvent(tcx, eq, op, &ot, op); + // TODO: Actually I just figured out that it should be possible to + // improve this by getting the next ot and op before the the above + // flip and continue the flipScanEdgeEvent here + // set new ot and op here and loop back to inScanArea test + // also need to set a new flip_triangle first + // Turns out at first glance that this is somewhat complicated + // so it will have to wait. + } else { + Point& newP = NextFlipPoint(ep, eq, ot, op); + FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, ot, newP); + } +} + +Sweep::~Sweep() +{ + // Clean up memory + for(unsigned int i = 0; i < nodes_.size(); i++) { + delete nodes_[i]; + } + } } diff --git a/poly2tri/sweep/sweep.h b/poly2tri/sweep/sweep.h index eb74e00c2b9103f256d1c895dd01441126ae6c99..a5f4b0a9a1854715afaf0d10b0dee81a7b1db217 100644 --- a/poly2tri/sweep/sweep.h +++ b/poly2tri/sweep/sweep.h @@ -43,242 +43,241 @@ namespace p2t { - class SweepContext; - struct Node; - struct Point; - struct Edge; - class Triangle; - - class Sweep - { - public: - - /** - * Triangulate - * - * @param tcx - */ - void Triangulate(SweepContext& tcx); - - /** - * Destructor - clean up memory - */ - ~Sweep(); - - private: - - /** - * Start sweeping the Y-sorted point set from bottom to top - * - * @param tcx - */ - void SweepPoints(SweepContext& tcx); - - /** - * Find closes node to the left of the new point and - * create a new triangle. If needed new holes and basins - * will be filled to. - * - * @param tcx - * @param point - * @return - */ - Node& PointEvent(SweepContext& tcx, Point& point); - - /** - * - * - * @param tcx - * @param edge - * @param node - */ - void EdgeEvent(SweepContext& tcx, Edge* edge, Node* node); - - void EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point); - - /** - * Creates a new front triangle and legalize it - * - * @param tcx - * @param point - * @param node - * @return - */ - Node& NewFrontTriangle(SweepContext& tcx, Point& point, Node& node); - - /** - * Adds a triangle to the advancing front to fill a hole. - * @param tcx - * @param node - middle node, that is the bottom of the hole - */ - void Fill(SweepContext& tcx, Node& node); - - /** - * Returns true if triangle was legalized - */ - bool Legalize(SweepContext& tcx, Triangle& t); - - /** - * <b>Requirement</b>:<br> - * 1. a,b and c form a triangle.<br> - * 2. a and d is know to be on opposite side of bc<br> - * <pre> - * a - * + - * / \ - * / \ - * b/ \c - * +-------+ - * / d \ - * / \ - * </pre> - * <b>Fact</b>: d has to be in area B to have a chance to be inside the circle formed by - * a,b and c<br> - * d is outside B if orient2d(a,b,d) or orient2d(c,a,d) is CW<br> - * This preknowledge gives us a way to optimize the incircle test - * @param a - triangle point, opposite d - * @param b - triangle point - * @param c - triangle point - * @param d - point opposite a - * @return true if d is inside circle, false if on circle edge - */ - bool Incircle(Point& pa, Point& pb, Point& pc, Point& pd); - - /** - * Rotates a triangle pair one vertex CW - *<pre> - * n2 n2 - * P +-----+ P +-----+ - * | t /| |\ t | - * | / | | \ | - * n1| / |n3 n1| \ |n3 - * | / | after CW | \ | - * |/ oT | | oT \| - * +-----+ oP +-----+ - * n4 n4 - * </pre> - */ - void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op); - - /** - * Fills holes in the Advancing Front - * - * - * @param tcx - * @param n - */ - void FillAdvancingFront(SweepContext& tcx, Node& n); - - // Decision-making about when to Fill hole. - // Contributed by ToolmakerSteve2 - bool LargeHole_DontFill(Node* node); - bool AngleExceeds90Degrees(Point* origin, Point* pa, Point* pb); - bool AngleExceedsPlus90DegreesOrIsNegative(Point* origin, Point* pa, Point* pb); - double Angle(Point& origin, Point& pa, Point& pb); - - /** - * - * @param node - middle node - * @return the angle between 3 front nodes - */ - double HoleAngle(Node& node); - - /** - * The basin angle is decided against the horizontal line [1,0] - */ - double BasinAngle(Node& node); - - /** - * Fills a basin that has formed on the Advancing Front to the right - * of given node.<br> - * First we decide a left,bottom and right node that forms the - * boundaries of the basin. Then we do a reqursive fill. - * - * @param tcx - * @param node - starting node, this or next node will be left node - */ - void FillBasin(SweepContext& tcx, Node& node); - - /** - * Recursive algorithm to fill a Basin with triangles - * - * @param tcx - * @param node - bottom_node - * @param cnt - counter used to alternate on even and odd numbers - */ - void FillBasinReq(SweepContext& tcx, Node* node); - - bool IsShallow(SweepContext& tcx, Node& node); - - bool IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq); - - void FillEdgeEvent(SweepContext& tcx, Edge* edge, Node* node); - - void FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node); - - void FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); - - void FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); - - void FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); - - void FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node); - - void FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); - - void FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); - - void FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); - - void FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p); - - /** - * After a flip we have two triangles and know that only one will still be - * intersecting the edge. So decide which to contiune with and legalize the other - * - * @param tcx - * @param o - should be the result of an orient2d( eq, op, ep ) - * @param t - triangle 1 - * @param ot - triangle 2 - * @param p - a point shared by both triangles - * @param op - another point shared by both triangles - * @return returns the triangle still intersecting the edge - */ - Triangle& NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op); - - /** - * When we need to traverse from one triangle to the next we need - * the point in current triangle that is the opposite point to the next - * triangle. - * - * @param ep - * @param eq - * @param ot - * @param op - * @return - */ - Point& NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op); - - /** - * Scan part of the FlipScan algorithm<br> - * When a triangle pair isn't flippable we will scan for the next - * point that is inside the flip triangle scan area. When found - * we generate a new flipEdgeEvent - * - * @param tcx - * @param ep - last point on the edge we are traversing - * @param eq - first point on the edge we are traversing - * @param flipTriangle - the current triangle sharing the point eq with edge - * @param t - * @param p - */ - void FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, Triangle& t, Point& p); - - void FinalizationPolygon(SweepContext& tcx); - - std::vector<Node*> nodes_; - - }; +class SweepContext; +struct Node; +struct Point; +struct Edge; +class Triangle; + +class Sweep { +public: + + /** + * Triangulate + * + * @param tcx + */ + void Triangulate(SweepContext& tcx); + + /** + * Destructor - clean up memory + */ + ~Sweep(); + +private: + + /** + * Start sweeping the Y-sorted point set from bottom to top + * + * @param tcx + */ + void SweepPoints(SweepContext& tcx); + + /** + * Find closes node to the left of the new point and + * create a new triangle. If needed new holes and basins + * will be filled to. + * + * @param tcx + * @param point + * @return + */ + Node& PointEvent(SweepContext& tcx, Point& point); + + /** + * + * + * @param tcx + * @param edge + * @param node + */ + void EdgeEvent(SweepContext& tcx, Edge* edge, Node* node); + + void EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point); + + /** + * Creates a new front triangle and legalize it + * + * @param tcx + * @param point + * @param node + * @return + */ + Node& NewFrontTriangle(SweepContext& tcx, Point& point, Node& node); + + /** + * Adds a triangle to the advancing front to fill a hole. + * @param tcx + * @param node - middle node, that is the bottom of the hole + */ + void Fill(SweepContext& tcx, Node& node); + + /** + * Returns true if triangle was legalized + */ + bool Legalize(SweepContext& tcx, Triangle& t); + + /** + * <b>Requirement</b>:<br> + * 1. a,b and c form a triangle.<br> + * 2. a and d is know to be on opposite side of bc<br> + * <pre> + * a + * + + * / \ + * / \ + * b/ \c + * +-------+ + * / d \ + * / \ + * </pre> + * <b>Fact</b>: d has to be in area B to have a chance to be inside the circle formed by + * a,b and c<br> + * d is outside B if orient2d(a,b,d) or orient2d(c,a,d) is CW<br> + * This preknowledge gives us a way to optimize the incircle test + * @param a - triangle point, opposite d + * @param b - triangle point + * @param c - triangle point + * @param d - point opposite a + * @return true if d is inside circle, false if on circle edge + */ + bool Incircle(Point& pa, Point& pb, Point& pc, Point& pd); + + /** + * Rotates a triangle pair one vertex CW + *<pre> + * n2 n2 + * P +-----+ P +-----+ + * | t /| |\ t | + * | / | | \ | + * n1| / |n3 n1| \ |n3 + * | / | after CW | \ | + * |/ oT | | oT \| + * +-----+ oP +-----+ + * n4 n4 + * </pre> + */ + void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op); + + /** + * Fills holes in the Advancing Front + * + * + * @param tcx + * @param n + */ + void FillAdvancingFront(SweepContext& tcx, Node& n); + + // Decision-making about when to Fill hole. + // Contributed by ToolmakerSteve2 + bool LargeHole_DontFill(Node* node); + bool AngleExceeds90Degrees(Point* origin, Point* pa, Point* pb); + bool AngleExceedsPlus90DegreesOrIsNegative(Point* origin, Point* pa, Point* pb); + double Angle(Point& origin, Point& pa, Point& pb); + + /** + * + * @param node - middle node + * @return the angle between 3 front nodes + */ + double HoleAngle(Node& node); + + /** + * The basin angle is decided against the horizontal line [1,0] + */ + double BasinAngle(Node& node); + + /** + * Fills a basin that has formed on the Advancing Front to the right + * of given node.<br> + * First we decide a left,bottom and right node that forms the + * boundaries of the basin. Then we do a reqursive fill. + * + * @param tcx + * @param node - starting node, this or next node will be left node + */ + void FillBasin(SweepContext& tcx, Node& node); + + /** + * Recursive algorithm to fill a Basin with triangles + * + * @param tcx + * @param node - bottom_node + * @param cnt - counter used to alternate on even and odd numbers + */ + void FillBasinReq(SweepContext& tcx, Node* node); + + bool IsShallow(SweepContext& tcx, Node& node); + + bool IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq); + + void FillEdgeEvent(SweepContext& tcx, Edge* edge, Node* node); + + void FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node); + + void FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + + void FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + + void FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + + void FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node); + + void FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + + void FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + + void FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node); + + void FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p); + + /** + * After a flip we have two triangles and know that only one will still be + * intersecting the edge. So decide which to contiune with and legalize the other + * + * @param tcx + * @param o - should be the result of an orient2d( eq, op, ep ) + * @param t - triangle 1 + * @param ot - triangle 2 + * @param p - a point shared by both triangles + * @param op - another point shared by both triangles + * @return returns the triangle still intersecting the edge + */ + Triangle& NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op); + + /** + * When we need to traverse from one triangle to the next we need + * the point in current triangle that is the opposite point to the next + * triangle. + * + * @param ep + * @param eq + * @param ot + * @param op + * @return + */ + Point& NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op); + + /** + * Scan part of the FlipScan algorithm<br> + * When a triangle pair isn't flippable we will scan for the next + * point that is inside the flip triangle scan area. When found + * we generate a new flipEdgeEvent + * + * @param tcx + * @param ep - last point on the edge we are traversing + * @param eq - first point on the edge we are traversing + * @param flipTriangle - the current triangle sharing the point eq with edge + * @param t + * @param p + */ + void FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, Triangle& t, Point& p); + + void FinalizationPolygon(SweepContext& tcx); + + std::vector<Node*> nodes_; + +}; } diff --git a/poly2tri/sweep/sweep_context.cpp b/poly2tri/sweep/sweep_context.cpp index e780e1c177051d76be4ca853776581f3aba3dd8d..74ae8b11ae2ad3b48df695fc0b4c8e50a59f5330 100644 --- a/poly2tri/sweep/sweep_context.cpp +++ b/poly2tri/sweep/sweep_context.cpp @@ -35,181 +35,182 @@ namespace p2t { SweepContext::SweepContext(std::vector<Point*> polyline) : - front_(0), - head_(0), - tail_(0), - af_head_(0), - af_middle_(0), - af_tail_(0) + front_(0), + head_(0), + tail_(0), + af_head_(0), + af_middle_(0), + af_tail_(0) { - basin = Basin(); - edge_event = EdgeEvent(); + basin = Basin(); + edge_event = EdgeEvent(); - points_ = polyline; + points_ = polyline; - InitEdges(points_); + InitEdges(points_); } void SweepContext::AddHole(std::vector<Point*> polyline) { - InitEdges(polyline); - for(unsigned int i = 0; i < polyline.size(); i++) { - points_.push_back(polyline[i]); - } + InitEdges(polyline); + for(unsigned int i = 0; i < polyline.size(); i++) { + points_.push_back(polyline[i]); + } } -void SweepContext::AddPoint(Point* point) { - points_.push_back(point); +void SweepContext::AddPoint(Point* point) +{ + points_.push_back(point); } std::vector<Triangle*> SweepContext::GetTriangles() { - return triangles_; + return triangles_; } std::list<Triangle*> SweepContext::GetMap() { - return map_; + return map_; } void SweepContext::InitTriangulation() { - double xmax(points_[0]->x), xmin(points_[0]->x); - double ymax(points_[0]->y), ymin(points_[0]->y); + double xmax(points_[0]->x), xmin(points_[0]->x); + double ymax(points_[0]->y), ymin(points_[0]->y); - // Calculate bounds. - for (unsigned int i = 0; i < points_.size(); i++) { - Point& p = *points_[i]; - if (p.x > xmax) - xmax = p.x; - if (p.x < xmin) - xmin = p.x; - if (p.y > ymax) - ymax = p.y; - if (p.y < ymin) - ymin = p.y; - } + // Calculate bounds. + for (unsigned int i = 0; i < points_.size(); i++) { + Point& p = *points_[i]; + if (p.x > xmax) + xmax = p.x; + if (p.x < xmin) + xmin = p.x; + if (p.y > ymax) + ymax = p.y; + if (p.y < ymin) + ymin = p.y; + } - double dx = kAlpha * (xmax - xmin); - double dy = kAlpha * (ymax - ymin); - head_ = new Point(xmax + dx, ymin - dy); - tail_ = new Point(xmin - dx, ymin - dy); + double dx = kAlpha * (xmax - xmin); + double dy = kAlpha * (ymax - ymin); + head_ = new Point(xmax + dx, ymin - dy); + tail_ = new Point(xmin - dx, ymin - dy); - // Sort points along y-axis - std::sort(points_.begin(), points_.end(), cmp); + // Sort points along y-axis + std::sort(points_.begin(), points_.end(), cmp); } void SweepContext::InitEdges(std::vector<Point*> polyline) { - int num_points = polyline.size(); - for (int i = 0; i < num_points; i++) { - int j = i < num_points - 1 ? i + 1 : 0; - edge_list.push_back(new Edge(*polyline[i], *polyline[j])); - } + int num_points = polyline.size(); + for (int i = 0; i < num_points; i++) { + int j = i < num_points - 1 ? i + 1 : 0; + edge_list.push_back(new Edge(*polyline[i], *polyline[j])); + } } Point* SweepContext::GetPoint(const int& index) { - return points_[index]; + return points_[index]; } void SweepContext::AddToMap(Triangle* triangle) { - map_.push_back(triangle); + map_.push_back(triangle); } Node& SweepContext::LocateNode(Point& point) { - // TODO implement search tree - return *front_->LocateNode(point.x); + // TODO implement search tree + return *front_->LocateNode(point.x); } void SweepContext::CreateAdvancingFront(std::vector<Node*> nodes) { - (void) nodes; - // Initial triangle - Triangle* triangle = new Triangle(*points_[0], *tail_, *head_); + (void) nodes; + // Initial triangle + Triangle* triangle = new Triangle(*points_[0], *tail_, *head_); - map_.push_back(triangle); + map_.push_back(triangle); - af_head_ = new Node(*triangle->GetPoint(1), *triangle); - af_middle_ = new Node(*triangle->GetPoint(0), *triangle); - af_tail_ = new Node(*triangle->GetPoint(2)); - front_ = new AdvancingFront(*af_head_, *af_tail_); + af_head_ = new Node(*triangle->GetPoint(1), *triangle); + af_middle_ = new Node(*triangle->GetPoint(0), *triangle); + af_tail_ = new Node(*triangle->GetPoint(2)); + front_ = new AdvancingFront(*af_head_, *af_tail_); - // TODO: More intuitive if head is middles next and not previous? - // so swap head and tail - af_head_->next = af_middle_; - af_middle_->next = af_tail_; - af_middle_->prev = af_head_; - af_tail_->prev = af_middle_; + // TODO: More intuitive if head is middles next and not previous? + // so swap head and tail + af_head_->next = af_middle_; + af_middle_->next = af_tail_; + af_middle_->prev = af_head_; + af_tail_->prev = af_middle_; } void SweepContext::RemoveNode(Node* node) { - delete node; + delete node; } void SweepContext::MapTriangleToNodes(Triangle& t) { - for (int i = 0; i < 3; i++) { - if (!t.GetNeighbor(i)) { - Node* n = front_->LocatePoint(t.PointCW(*t.GetPoint(i))); - if (n) - n->triangle = &t; - } - } + for (int i = 0; i < 3; i++) { + if (!t.GetNeighbor(i)) { + Node* n = front_->LocatePoint(t.PointCW(*t.GetPoint(i))); + if (n) + n->triangle = &t; + } + } } void SweepContext::RemoveFromMap(Triangle* triangle) { - map_.remove(triangle); + map_.remove(triangle); } void SweepContext::MeshClean(Triangle& triangle) { - std::vector<Triangle *> triangles; - triangles.push_back(&triangle); + std::vector<Triangle *> triangles; + triangles.push_back(&triangle); - while(!triangles.empty()){ - Triangle *t = triangles.back(); - triangles.pop_back(); + while(!triangles.empty()) { + Triangle *t = triangles.back(); + triangles.pop_back(); - if (t != NULL && !t->IsInterior()) { - t->IsInterior(true); - triangles_.push_back(t); - for (int i = 0; i < 3; i++) { - if (!t->constrained_edge[i]) - triangles.push_back(t->GetNeighbor(i)); - } - } - } + if (t != NULL && !t->IsInterior()) { + t->IsInterior(true); + triangles_.push_back(t); + for (int i = 0; i < 3; i++) { + if (!t->constrained_edge[i]) + triangles.push_back(t->GetNeighbor(i)); + } + } + } } SweepContext::~SweepContext() { - // Clean up memory + // Clean up memory - delete head_; - delete tail_; - delete front_; - delete af_head_; - delete af_middle_; - delete af_tail_; + delete head_; + delete tail_; + delete front_; + delete af_head_; + delete af_middle_; + delete af_tail_; - typedef std::list<Triangle*> type_list; + typedef std::list<Triangle*> type_list; - for(type_list::iterator iter = map_.begin(); iter != map_.end(); ++iter) { - Triangle* ptr = *iter; - delete ptr; - } + for(type_list::iterator iter = map_.begin(); iter != map_.end(); ++iter) { + Triangle* ptr = *iter; + delete ptr; + } for(unsigned int i = 0; i < edge_list.size(); i++) { - delete edge_list[i]; - } + delete edge_list[i]; + } } diff --git a/poly2tri/sweep/sweep_context.h b/poly2tri/sweep/sweep_context.h index 83c2b4c25b20df9a5caa95cfe83c43647eb4a621..6ae782d39b29afde11e95a1830ba83068e22fa4c 100644 --- a/poly2tri/sweep/sweep_context.h +++ b/poly2tri/sweep/sweep_context.h @@ -28,159 +28,156 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - + #ifndef SWEEP_CONTEXT_H #define SWEEP_CONTEXT_H - + #include <list> #include <vector> #include <cstddef> - - namespace p2t { - - // Inital triangle factor, seed triangle will extend 30% of - // PointSet width to both left and right. - const double kAlpha = 0.3; - - struct Point; - class Triangle; - struct Node; - struct Edge; - class AdvancingFront; - - class SweepContext { - public: - - /// Constructor - SweepContext(std::vector<Point*> polyline); - /// Destructor - ~SweepContext(); - - void set_head(Point* p1); - - Point* head(); - - void set_tail(Point* p1); - - Point* tail(); - - int point_count(); - - Node& LocateNode(Point& point); - - void RemoveNode(Node* node); - - void CreateAdvancingFront(std::vector<Node*> nodes); - - /// Try to map a node to all sides of this triangle that don't have a neighbor - void MapTriangleToNodes(Triangle& t); - - void AddToMap(Triangle* triangle); - - Point* GetPoint(const int& index); - - Point* GetPoints(); - - void RemoveFromMap(Triangle* triangle); - - void AddHole(std::vector<Point*> polyline); - - void AddPoint(Point* point); - - AdvancingFront* front(); - - void MeshClean(Triangle& triangle); - - std::vector<Triangle*> GetTriangles(); - std::list<Triangle*> GetMap(); - - std::vector<Edge*> edge_list; - - struct Basin { - Node* left_node; - Node* bottom_node; - Node* right_node; - double width; - bool left_highest; - - Basin() : left_node(NULL), bottom_node(NULL), right_node(NULL), width(0.0), left_highest(false) - { - } - - void Clear() - { - left_node = NULL; - bottom_node = NULL; - right_node = NULL; - width = 0.0; - left_highest = false; - } - }; - - struct EdgeEvent { - Edge* constrained_edge; - bool right; - - EdgeEvent() : constrained_edge(NULL), right(false) - { - } - }; - - Basin basin; - EdgeEvent edge_event; - - private: - - friend class Sweep; - - std::vector<Triangle*> triangles_; - std::list<Triangle*> map_; - std::vector<Point*> points_; - - // Advancing front - AdvancingFront* front_; - // head point used with advancing front - Point* head_; - // tail point used with advancing front - Point* tail_; - - Node *af_head_, *af_middle_, *af_tail_; - - void InitTriangulation(); - void InitEdges(std::vector<Point*> polyline); - - }; - - inline AdvancingFront* SweepContext::front() - { - return front_; - } - - inline int SweepContext::point_count() - { - return points_.size(); - } - - inline void SweepContext::set_head(Point* p1) - { - head_ = p1; - } - - inline Point* SweepContext::head() - { - return head_; - } - - inline void SweepContext::set_tail(Point* p1) - { - tail_ = p1; - } - - inline Point* SweepContext::tail() - { - return tail_; - } - - } - + +namespace p2t { + +// Inital triangle factor, seed triangle will extend 30% of +// PointSet width to both left and right. +const double kAlpha = 0.3; + +struct Point; +class Triangle; +struct Node; +struct Edge; +class AdvancingFront; + +class SweepContext { +public: + + /// Constructor + SweepContext(std::vector<Point*> polyline); + /// Destructor + ~SweepContext(); + + void set_head(Point* p1); + + Point* head(); + + void set_tail(Point* p1); + + Point* tail(); + + int point_count(); + + Node& LocateNode(Point& point); + + void RemoveNode(Node* node); + + void CreateAdvancingFront(std::vector<Node*> nodes); + + /// Try to map a node to all sides of this triangle that don't have a neighbor + void MapTriangleToNodes(Triangle& t); + + void AddToMap(Triangle* triangle); + + Point* GetPoint(const int& index); + + Point* GetPoints(); + + void RemoveFromMap(Triangle* triangle); + + void AddHole(std::vector<Point*> polyline); + + void AddPoint(Point* point); + + AdvancingFront* front(); + + void MeshClean(Triangle& triangle); + + std::vector<Triangle*> GetTriangles(); + std::list<Triangle*> GetMap(); + + std::vector<Edge*> edge_list; + + struct Basin { + Node* left_node; + Node* bottom_node; + Node* right_node; + double width; + bool left_highest; + + Basin() : left_node(NULL), bottom_node(NULL), right_node(NULL), width(0.0), left_highest(false) { + } + + void Clear() { + left_node = NULL; + bottom_node = NULL; + right_node = NULL; + width = 0.0; + left_highest = false; + } + }; + + struct EdgeEvent { + Edge* constrained_edge; + bool right; + + EdgeEvent() : constrained_edge(NULL), right(false) { + } + }; + + Basin basin; + EdgeEvent edge_event; + +private: + + friend class Sweep; + + std::vector<Triangle*> triangles_; + std::list<Triangle*> map_; + std::vector<Point*> points_; + + // Advancing front + AdvancingFront* front_; + // head point used with advancing front + Point* head_; + // tail point used with advancing front + Point* tail_; + + Node *af_head_, *af_middle_, *af_tail_; + + void InitTriangulation(); + void InitEdges(std::vector<Point*> polyline); + +}; + +inline AdvancingFront* SweepContext::front() +{ + return front_; +} + +inline int SweepContext::point_count() +{ + return points_.size(); +} + +inline void SweepContext::set_head(Point* p1) +{ + head_ = p1; +} + +inline Point* SweepContext::head() +{ + return head_; +} + +inline void SweepContext::set_tail(Point* p1) +{ + tail_ = p1; +} + +inline Point* SweepContext::tail() +{ + return tail_; +} + +} + #endif diff --git a/routing/AccessPoint.cpp b/routing/AccessPoint.cpp index b385a83c37e495a8f753d27275caa2ae05b509be..b3aaa4e6234922945e50b841dd6ee13dd46982cf 100644 --- a/routing/AccessPoint.cpp +++ b/routing/AccessPoint.cpp @@ -32,156 +32,174 @@ using namespace std; -AccessPoint::AccessPoint(int id, double center[2],double radius) { - _id=id; - _center[0]=center[0]; - _center[1]=center[1]; - _radius=radius; - _finaExitToOutside=false; - _finalGoalOutside=false; - _room1ID=-1; - _room2ID=-1; - _connectingAPs.clear(); - _mapDestToDist.clear(); - pCentre=Point(center[0],center[1]); - _transitPedestrians = vector<Pedestrian*>(); - _connectingAPs = vector<AccessPoint*>(); - _isClosed=0; - _navLine=NULL; +AccessPoint::AccessPoint(int id, double center[2],double radius) +{ + _id=id; + _center[0]=center[0]; + _center[1]=center[1]; + _radius=radius; + _finaExitToOutside=false; + _finalGoalOutside=false; + _room1ID=-1; + _room2ID=-1; + _connectingAPs.clear(); + _mapDestToDist.clear(); + pCentre=Point(center[0],center[1]); + _transitPedestrians = vector<Pedestrian*>(); + _connectingAPs = vector<AccessPoint*>(); + _isClosed=0; + _navLine=NULL; } -AccessPoint::~AccessPoint() { - //if(_navLine) delete _navLine; +AccessPoint::~AccessPoint() +{ + //if(_navLine) delete _navLine; } int AccessPoint::GetID() { - return _id; + return _id; } -int AccessPoint::IsClosed(){ - return _isClosed; +int AccessPoint::IsClosed() +{ + return _isClosed; } -void AccessPoint::SetClosed(int isClosed){ - _isClosed=isClosed; +void AccessPoint::SetClosed(int isClosed) +{ + _isClosed=isClosed; } void AccessPoint::SetFinalExitToOutside(bool isFinal) { - _finaExitToOutside=isFinal; + _finaExitToOutside=isFinal; } bool AccessPoint::GetFinalExitToOutside() { - return _finaExitToOutside; + return _finaExitToOutside; } -const Point& AccessPoint::GetCentre() const{ - return pCentre; +const Point& AccessPoint::GetCentre() const +{ + return pCentre; } -void AccessPoint::SetFinalGoalOutside(bool isFinal) { - _finalGoalOutside=isFinal; +void AccessPoint::SetFinalGoalOutside(bool isFinal) +{ + _finalGoalOutside=isFinal; } -bool AccessPoint::GetFinalGoalOutside(){ - return _finalGoalOutside; +bool AccessPoint::GetFinalGoalOutside() +{ + return _finalGoalOutside; } //TODO: possibly remove -void AccessPoint::AddIntermediateDest(int final, int inter){ - _mapDestToAp[final]=inter; +void AccessPoint::AddIntermediateDest(int final, int inter) +{ + _mapDestToAp[final]=inter; } -void AccessPoint::AddFinalDestination(int UID, double distance){ - _mapDestToDist[UID]=distance; +void AccessPoint::AddFinalDestination(int UID, double distance) +{ + _mapDestToDist[UID]=distance; } -double AccessPoint::GetDistanceTo(int UID){ - //this is probably a final destination - if(_mapDestToDist.count(UID)==0){ - Log->Write("ERROR:\tNo route to destination [ %d ]",UID); - Log->Write("ERROR:\tCheck your configuration file"); - Dump(); - exit(EXIT_FAILURE); - } - return _mapDestToDist[UID]; +double AccessPoint::GetDistanceTo(int UID) +{ + //this is probably a final destination + if(_mapDestToDist.count(UID)==0) { + Log->Write("ERROR:\tNo route to destination [ %d ]",UID); + Log->Write("ERROR:\tCheck your configuration file"); + Dump(); + exit(EXIT_FAILURE); + } + return _mapDestToDist[UID]; } -double AccessPoint::GetDistanceTo(AccessPoint* ap){ - return (pCentre-ap->GetCentre()).Norm(); +double AccessPoint::GetDistanceTo(AccessPoint* ap) +{ + return (pCentre-ap->GetCentre()).Norm(); } -void AccessPoint::AddConnectingAP(AccessPoint* ap){ - //only add of not already inside - for(unsigned int p=0;p<_connectingAPs.size();p++){ - if(_connectingAPs[p]->GetID()==ap->GetID()) return; - } - _connectingAPs.push_back(ap); +void AccessPoint::AddConnectingAP(AccessPoint* ap) +{ + //only add of not already inside + for(unsigned int p=0; p<_connectingAPs.size(); p++) { + if(_connectingAPs[p]->GetID()==ap->GetID()) return; + } + _connectingAPs.push_back(ap); } //TODO: remove this one -int AccessPoint::GetNextApTo(int UID){ - //this is probably a final destination - if(_mapDestToAp.count(UID)==0){ - Log->Write("ERROR:\tNo route to destination [ %d ]",UID); - Log->Write("ERROR:\t Did you forget to define the goal in the configuration file?"); - Dump(); - exit(EXIT_FAILURE); - } - return _mapDestToAp[UID]; +int AccessPoint::GetNextApTo(int UID) +{ + //this is probably a final destination + if(_mapDestToAp.count(UID)==0) { + Log->Write("ERROR:\tNo route to destination [ %d ]",UID); + Log->Write("ERROR:\t Did you forget to define the goal in the configuration file?"); + Dump(); + exit(EXIT_FAILURE); + } + return _mapDestToAp[UID]; } -int AccessPoint::GetNearestTransitAPTO(int UID){ - const vector <AccessPoint*>& possibleDest=_navigationGraphTo[UID]; - - if(possibleDest.size()==0){ - return -1; - }else if (possibleDest.size()==1){ - return possibleDest[0]->GetID(); - }else { - AccessPoint* best_ap=possibleDest[0]; - double min_dist=GetDistanceTo(best_ap);// + best_ap->GetDistanceTo(UID); // FIXME: add the shortest distance to outside - - for (unsigned int i=0;i<possibleDest.size();i++){ - double tmp= GetDistanceTo(possibleDest[i]); - if(tmp<min_dist){ - min_dist=tmp; - best_ap=possibleDest[i]; - } - } - return best_ap->GetID(); - } +int AccessPoint::GetNearestTransitAPTO(int UID) +{ + const vector <AccessPoint*>& possibleDest=_navigationGraphTo[UID]; + + if(possibleDest.size()==0) { + return -1; + } else if (possibleDest.size()==1) { + return possibleDest[0]->GetID(); + } else { + AccessPoint* best_ap=possibleDest[0]; + double min_dist=GetDistanceTo(best_ap);// + best_ap->GetDistanceTo(UID); // FIXME: add the shortest distance to outside + + for (unsigned int i=0; i<possibleDest.size(); i++) { + double tmp= GetDistanceTo(possibleDest[i]); + if(tmp<min_dist) { + min_dist=tmp; + best_ap=possibleDest[i]; + } + } + return best_ap->GetID(); + } } -void AccessPoint::setConnectingRooms(int r1, int r2){ - _room1ID=r1; - _room2ID=r2; +void AccessPoint::setConnectingRooms(int r1, int r2) +{ + _room1ID=r1; + _room2ID=r2; } -double AccessPoint::DistanceTo(double x, double y){ +double AccessPoint::DistanceTo(double x, double y) +{ - return sqrt((x-_center[0])*(x-_center[0]) + (y-_center[1])*(y-_center[1])); + return sqrt((x-_center[0])*(x-_center[0]) + (y-_center[1])*(y-_center[1])); } -bool AccessPoint::isInRange(int roomID){ - if((roomID!=_room1ID) && (roomID!=_room2ID)){ - return false; - } - return true; +bool AccessPoint::isInRange(int roomID) +{ + if((roomID!=_room1ID) && (roomID!=_room2ID)) { + return false; + } + return true; } -bool AccessPoint::IsInRange(double xPed, double yPed, int roomID){ +bool AccessPoint::IsInRange(double xPed, double yPed, int roomID) +{ - if((roomID!=_room1ID)&& (roomID!=_room2ID)){ - return false; - } - if (((xPed - _center[0]) * (xPed - _center[0]) + (yPed - _center[1]) * (yPed - - _center[1])) <= _radius * _radius) - return true; + if((roomID!=_room1ID)&& (roomID!=_room2ID)) { + return false; + } + if (((xPed - _center[0]) * (xPed - _center[0]) + (yPed - _center[1]) * (yPed + - _center[1])) <= _radius * _radius) + return true; - return false; + return false; } //void AccessPoint::DeleteTransitPed(Pedestrian* ped){ @@ -199,103 +217,113 @@ bool AccessPoint::IsInRange(double xPed, double yPed, int roomID){ // _transitPedestrians.push_back(ped); //} -void AccessPoint::SetNavLine(NavLine* line) { - _navLine=line; +void AccessPoint::SetNavLine(NavLine* line) +{ + _navLine=line; } -NavLine* AccessPoint::GetNavLine() const { - return _navLine; +NavLine* AccessPoint::GetNavLine() const +{ + return _navLine; } //const vector<Pedestrian*>& AccessPoint::GetAllTransitPed() const{ // return _transitPedestrians; //} -const vector <AccessPoint*>& AccessPoint::GetConnectingAPs(){ - return _connectingAPs; +const vector <AccessPoint*>& AccessPoint::GetConnectingAPs() +{ + return _connectingAPs; } -void AccessPoint::RemoveConnectingAP(AccessPoint* ap){ - vector<AccessPoint*>::iterator it; - it = find (_connectingAPs.begin(), _connectingAPs.end(), ap); - if(it==_connectingAPs.end()){ - cout<<" there is no connection to AP: "<< ap->GetID()<<endl; - }else{ - _connectingAPs.erase(it); - } +void AccessPoint::RemoveConnectingAP(AccessPoint* ap) +{ + vector<AccessPoint*>::iterator it; + it = find (_connectingAPs.begin(), _connectingAPs.end(), ap); + if(it==_connectingAPs.end()) { + cout<<" there is no connection to AP: "<< ap->GetID()<<endl; + } else { + _connectingAPs.erase(it); + } } -const vector <AccessPoint*>& AccessPoint::GetTransitAPsTo(int UID){ - return _navigationGraphTo[UID]; +const vector <AccessPoint*>& AccessPoint::GetTransitAPsTo(int UID) +{ + return _navigationGraphTo[UID]; } -void AccessPoint::AddTransitAPsTo(int UID,AccessPoint* ap){ - _navigationGraphTo[UID].push_back(ap); +void AccessPoint::AddTransitAPsTo(int UID,AccessPoint* ap) +{ + _navigationGraphTo[UID].push_back(ap); } -void AccessPoint::Reset(int UID){ - _navigationGraphTo[UID].clear(); +void AccessPoint::Reset(int UID) +{ + _navigationGraphTo[UID].clear(); } -void AccessPoint::SetFriendlyName(const std::string& name){ - _friendlyName=name; +void AccessPoint::SetFriendlyName(const std::string& name) +{ + _friendlyName=name; } -const std::string AccessPoint::GetFriendlyName(){ - return _friendlyName; +const std::string AccessPoint::GetFriendlyName() +{ + return _friendlyName; } -void AccessPoint::Dump(){ - - cout<<endl<<"--------> Dumping AP <-----------"<<endl<<endl; - //cout<<" ID: " <<_id<<" centre = [ "<< _center[0] <<", " <<_center[1] <<" ]"<<endl; - cout<<" Friendly ID: " <<_friendlyName<<" centre = [ "<< _center[0] <<", " <<_center[1] <<" ]"<<endl; - cout<<" Real ID: " <<_id<<endl; - - cout <<" Is final exit to outside :"<<GetFinalExitToOutside()<<endl; - cout <<" Distance to final goals"<<endl; - - for(std::map<int, double>::iterator p = _mapDestToDist.begin(); p != _mapDestToDist.end(); ++p) { - cout<<"\t [ "<<p->first<<", " << p->second<<" m ]"; - } - cout<<endl<<endl; - - cout<<" transit to final goals:"<<endl; - for(std::map<int, std::vector<AccessPoint*> >::iterator p = _navigationGraphTo.begin(); p != _navigationGraphTo.end(); ++p) { - cout<<endl<<"\t to UID ---> [ "<<p->first <<" ]"; - - if(p->second.size()==0) { - cout<<"\t ---> [ Nothing ]"; - } else { - - for(unsigned int i=0;i<p->second.size();i++){ - cout<<"\t distance ---> [ "<<GetDistanceTo(p->second[i])+p->second[i]->GetDistanceTo(p->first) <<" m via "<<p->second[i]->GetID() <<" ]"; - //cout<<"\t distance ---> [ "<<p->second[i]->GetID()<<" @ " << GetDistanceTo(p->first)<<" ]"; - } - } - } - - cout<<endl<<endl; - - cout<<" connected to aps : " ; - for(unsigned int p=0;p<_connectingAPs.size();p++){ - //cout<<" [ "<<_connectingAPs[p]->GetID()<<" , "<<_connectingAPs[p]->GetDistanceTo(this)<<" m ]"; - cout<<endl<<"\t [ "<<_connectingAPs[p]->GetID()<<"_"<<_connectingAPs[p]->GetFriendlyName()<<" , "<<_connectingAPs[p]->GetDistanceTo(this)<<" m ]"; - } - - cout<<endl<<endl; - cout <<" queue [ "; - for(unsigned int p=0;p<_transitPedestrians.size();p++){ - cout<<" "<<_transitPedestrians[p]->GetID(); - } - cout<<" ]"<<endl; +void AccessPoint::Dump() +{ - //cout<<endl<<" connected to rooms: "<<_room1ID<<" and "<<_room2ID<<endl; - cout<<endl; - cout<<endl<<"------------------------------"<<endl<<endl; + cout<<endl<<"--------> Dumping AP <-----------"<<endl<<endl; + //cout<<" ID: " <<_id<<" centre = [ "<< _center[0] <<", " <<_center[1] <<" ]"<<endl; + cout<<" Friendly ID: " <<_friendlyName<<" centre = [ "<< _center[0] <<", " <<_center[1] <<" ]"<<endl; + cout<<" Real ID: " <<_id<<endl; + + cout <<" Is final exit to outside :"<<GetFinalExitToOutside()<<endl; + cout <<" Distance to final goals"<<endl; + + for(std::map<int, double>::iterator p = _mapDestToDist.begin(); p != _mapDestToDist.end(); ++p) { + cout<<"\t [ "<<p->first<<", " << p->second<<" m ]"; + } + cout<<endl<<endl; + + cout<<" transit to final goals:"<<endl; + for(std::map<int, std::vector<AccessPoint*> >::iterator p = _navigationGraphTo.begin(); p != _navigationGraphTo.end(); ++p) { + cout<<endl<<"\t to UID ---> [ "<<p->first <<" ]"; + + if(p->second.size()==0) { + cout<<"\t ---> [ Nothing ]"; + } else { + + for(unsigned int i=0; i<p->second.size(); i++) { + cout<<"\t distance ---> [ "<<GetDistanceTo(p->second[i])+p->second[i]->GetDistanceTo(p->first) <<" m via "<<p->second[i]->GetID() <<" ]"; + //cout<<"\t distance ---> [ "<<p->second[i]->GetID()<<" @ " << GetDistanceTo(p->first)<<" ]"; + } + } + } + + cout<<endl<<endl; + + cout<<" connected to aps : " ; + for(unsigned int p=0; p<_connectingAPs.size(); p++) { + //cout<<" [ "<<_connectingAPs[p]->GetID()<<" , "<<_connectingAPs[p]->GetDistanceTo(this)<<" m ]"; + cout<<endl<<"\t [ "<<_connectingAPs[p]->GetID()<<"_"<<_connectingAPs[p]->GetFriendlyName()<<" , "<<_connectingAPs[p]->GetDistanceTo(this)<<" m ]"; + } + + cout<<endl<<endl; + cout <<" queue [ "; + for(unsigned int p=0; p<_transitPedestrians.size(); p++) { + cout<<" "<<_transitPedestrians[p]->GetID(); + } + cout<<" ]"<<endl; + + //cout<<endl<<" connected to rooms: "<<_room1ID<<" and "<<_room2ID<<endl; + cout<<endl; + cout<<endl<<"------------------------------"<<endl<<endl; } diff --git a/routing/AccessPoint.h b/routing/AccessPoint.h index 5bb6f233823560d27c5c092e71a72bc7a1d247aa..c8194375517de75fdbb0812493f0167674c06886 100644 --- a/routing/AccessPoint.h +++ b/routing/AccessPoint.h @@ -26,10 +26,10 @@ * * */ - + #ifndef ACCESSPOINT_H_ #define ACCESSPOINT_H_ - + #include <map> #include <vector> #include <cmath> @@ -39,196 +39,200 @@ #include "../pedestrian/Pedestrian.h" #include "../geometry/Point.h" #include "../geometry/Line.h" - - class AccessPoint { - public: - + +class AccessPoint { +public: + /** * create a new access point with the provided data - * - * @param id - * @param center - * @param radius + * + * @param id + * @param center + * @param radius */ - + AccessPoint(int id, double center[2],double radius=0.30); - - /** - * - * destroy the access point - */ - virtual ~AccessPoint(); - - - /** - * @return the Id of the access point - */ - int GetID(); - - - /** - * determines if the given coordinates (x ,y) are in the range of that Aps. - * - * @param x - * @param y - * @return - */ - bool IsInRange(double xPed, double yPed, int roomID); - - - /** - * given the actual room of the pedestrian - * determine if that AP is 'visible' - */ - - bool isInRange(int roomID); - - /** - * each AP is connected to at most 2 rooms - * @param r1 - * @param r1 - */ - void setConnectingRooms(int r1, int r2); - - int GetConnectingRoom1() {return _room1ID;}; - int GetConnectingRoom2() {return _room2ID;}; - - /** - * return the distance to the point x ,y - * @param x - * @param y - * @return - */ - double DistanceTo(double x, double y); - - /** - * set/get a human readable name for this points. - * t23 means Transition with id 23 - * c23 means Crossing with id 23 - * h23 means Hlines with id 23 - */ - void SetFriendlyName(const std::string& name); - - /** - * set/get a human readable name for this points. - * t23 means Transition with id 23 - * c23 means Crossing with id 23 - * h23 means Hlines with id 23 - */ - const std::string GetFriendlyName(); - - /** - * dump the class - */ - void Dump(); - - /** - * Set/Get the centre of the navigation line defining this access point - */ - const Point& GetCentre() const; - - /** - * True if this is the last exit that leads to the outside - */ - void SetFinalExitToOutside(bool isFinal); - - /** - * True if this is the last exit that leads to the outside - */ - bool GetFinalExitToOutside(); - - /** - * @return true if the door is closed - */ - int IsClosed(); - - /** - * Close the door - * @param isClosed - */ - void SetClosed(int isClosed); - - /** - * Set/Get the navigation line. - * The direction taken by the pedestrian strongly depends on this line. - */ - void SetNavLine(NavLine* line); - - /** - * Set/Get the navigation line. - * The direction taken by the pedestrian strongly depends on this line. - */ - NavLine* GetNavLine() const; - - /** - * True if this is a goal outside the building - */ - void SetFinalGoalOutside(bool isFinal); - - /** - * True if this is a goal outside the building - */ - bool GetFinalGoalOutside(); - - void AddIntermediateDest(int final, int inter); - void AddFinalDestination(int UID, double distance); - double GetDistanceTo(int UID); - double GetDistanceTo(AccessPoint* ap); - void RemoveConnectingAP(AccessPoint* ap); - - // reset all setting relative to the destination - void Reset(int UID=FINAL_DEST_OUT); - - //FIXME: remove those functions - void AddConnectingAP(AccessPoint* ap); - int GetNextApTo(int UID=FINAL_DEST_OUT); //default is the shortest path to the outside ( -1 ) - const std::vector <AccessPoint*>& GetConnectingAPs(); - - - const std::vector <AccessPoint*>& GetTransitAPsTo(int UID=FINAL_DEST_OUT); - int GetNearestTransitAPTO(int UID=FINAL_DEST_OUT); - void AddTransitAPsTo(int UID,AccessPoint* ap); - - - // re routing functions - //void AddTransitPed(Pedestrian* ped); - //void DeleteTransitPed(Pedestrian* ped); - //const std::vector<Pedestrian*>& GetAllTransitPed() const; - - - - private: - int _id; - double _center[2]; - double _radius; - /// true if this exit leads to outside - bool _finaExitToOutside; - /// true if this a goal outside the building - bool _finalGoalOutside; - int _room1ID; - int _room2ID; - Point pCentre; - NavLine* _navLine; - std::vector<Pedestrian*> _transitPedestrians; - int _isClosed; - std::string _friendlyName; - - - // stores the connecting APs - std::vector<AccessPoint*>_connectingAPs; - - // store part of a graph - // map a final destination to the next ap to reach it - // store the nearest AP to reach the destination - std::map<int, int> _mapDestToAp; - - // store part of the weight matrix - // store the total distance to the destination int - std::map <int,double> _mapDestToDist; - - //store the navigation graph - std::map<int,std::vector<AccessPoint*> > _navigationGraphTo; - - }; - + + /** + * + * destroy the access point + */ + virtual ~AccessPoint(); + + + /** + * @return the Id of the access point + */ + int GetID(); + + + /** + * determines if the given coordinates (x ,y) are in the range of that Aps. + * + * @param x + * @param y + * @return + */ + bool IsInRange(double xPed, double yPed, int roomID); + + + /** + * given the actual room of the pedestrian + * determine if that AP is 'visible' + */ + + bool isInRange(int roomID); + + /** + * each AP is connected to at most 2 rooms + * @param r1 + * @param r1 + */ + void setConnectingRooms(int r1, int r2); + + int GetConnectingRoom1() { + return _room1ID; + }; + int GetConnectingRoom2() { + return _room2ID; + }; + + /** + * return the distance to the point x ,y + * @param x + * @param y + * @return + */ + double DistanceTo(double x, double y); + + /** + * set/get a human readable name for this points. + * t23 means Transition with id 23 + * c23 means Crossing with id 23 + * h23 means Hlines with id 23 + */ + void SetFriendlyName(const std::string& name); + + /** + * set/get a human readable name for this points. + * t23 means Transition with id 23 + * c23 means Crossing with id 23 + * h23 means Hlines with id 23 + */ + const std::string GetFriendlyName(); + + /** + * dump the class + */ + void Dump(); + + /** + * Set/Get the centre of the navigation line defining this access point + */ + const Point& GetCentre() const; + + /** + * True if this is the last exit that leads to the outside + */ + void SetFinalExitToOutside(bool isFinal); + + /** + * True if this is the last exit that leads to the outside + */ + bool GetFinalExitToOutside(); + + /** + * @return true if the door is closed + */ + int IsClosed(); + + /** + * Close the door + * @param isClosed + */ + void SetClosed(int isClosed); + + /** + * Set/Get the navigation line. + * The direction taken by the pedestrian strongly depends on this line. + */ + void SetNavLine(NavLine* line); + + /** + * Set/Get the navigation line. + * The direction taken by the pedestrian strongly depends on this line. + */ + NavLine* GetNavLine() const; + + /** + * True if this is a goal outside the building + */ + void SetFinalGoalOutside(bool isFinal); + + /** + * True if this is a goal outside the building + */ + bool GetFinalGoalOutside(); + + void AddIntermediateDest(int final, int inter); + void AddFinalDestination(int UID, double distance); + double GetDistanceTo(int UID); + double GetDistanceTo(AccessPoint* ap); + void RemoveConnectingAP(AccessPoint* ap); + + // reset all setting relative to the destination + void Reset(int UID=FINAL_DEST_OUT); + + //FIXME: remove those functions + void AddConnectingAP(AccessPoint* ap); + int GetNextApTo(int UID=FINAL_DEST_OUT); //default is the shortest path to the outside ( -1 ) + const std::vector <AccessPoint*>& GetConnectingAPs(); + + + const std::vector <AccessPoint*>& GetTransitAPsTo(int UID=FINAL_DEST_OUT); + int GetNearestTransitAPTO(int UID=FINAL_DEST_OUT); + void AddTransitAPsTo(int UID,AccessPoint* ap); + + + // re routing functions + //void AddTransitPed(Pedestrian* ped); + //void DeleteTransitPed(Pedestrian* ped); + //const std::vector<Pedestrian*>& GetAllTransitPed() const; + + + +private: + int _id; + double _center[2]; + double _radius; + /// true if this exit leads to outside + bool _finaExitToOutside; + /// true if this a goal outside the building + bool _finalGoalOutside; + int _room1ID; + int _room2ID; + Point pCentre; + NavLine* _navLine; + std::vector<Pedestrian*> _transitPedestrians; + int _isClosed; + std::string _friendlyName; + + + // stores the connecting APs + std::vector<AccessPoint*>_connectingAPs; + + // store part of a graph + // map a final destination to the next ap to reach it + // store the nearest AP to reach the destination + std::map<int, int> _mapDestToAp; + + // store part of the weight matrix + // store the total distance to the destination int + std::map <int,double> _mapDestToDist; + + //store the navigation graph + std::map<int,std::vector<AccessPoint*> > _navigationGraphTo; + +}; + #endif /* ACCESSPOINT_H_ */ diff --git a/routing/CognitiveMapRouter.cpp b/routing/CognitiveMapRouter.cpp index 715f5c699312584fdc053d997a37627166784919..a3d2fa7e7d5ccfd7b1fd61fa1b00dd0089e3b392 100644 --- a/routing/CognitiveMapRouter.cpp +++ b/routing/CognitiveMapRouter.cpp @@ -27,72 +27,72 @@ CognitiveMapRouter::CognitiveMapRouter() CognitiveMapRouter::~CognitiveMapRouter() { - delete cm_storage; + delete cm_storage; } int CognitiveMapRouter::FindExit(Pedestrian * p) { - //Checks if the Pedestrian once got a destination and calls init functions if needed (if no dest before) - CheckAndInitPedestrian(p); - - //Check if the Pedestrian already has a Dest. or changed subroom and needs a new one. - if(p->GetNextDestination() == -1 || p->ChangedSubRoom()) { - //execute periodical sensors - sensor_manager->execute(p, SensorManager::PERIODIC); - - //check if there is a way to the outside the pedestrian knows (in the cognitive map) - const NavLine * destination = NULL; - destination = (*cm_storage)[p]->GetDestination(); - if(destination == NULL) { - //no destination was found, now we could start the discovery! - //1. run the no_way sensors for room discovery. - sensor_manager->execute(p, SensorManager::NO_WAY); - - //check if this was enough for finding a global path to the exit - destination = (*cm_storage)[p]->GetDestination(); - - if(destination == NULL) { - //we still do not have a way. lets take the "best" local edge - //for this we don't calculate the cost to exit but calculte the cost for the edges at the actual vertex. - destination = (*cm_storage)[p]->GetLocalDestination(); - } - } - - //if we still could not found any destination we are lost! Pedestrian will be deleted - //no destination should just appear in bug case or closed rooms. - if(destination == NULL) { - Log->Write("ERROR: \t One Pedestrian (ID: %i) was not able to find any destination", p->GetID()); - return -1; - } - - p->SetExitLine(destination); - p->SetExitIndex(destination->GetUniqueID()); - } - return 1; + //Checks if the Pedestrian once got a destination and calls init functions if needed (if no dest before) + CheckAndInitPedestrian(p); + + //Check if the Pedestrian already has a Dest. or changed subroom and needs a new one. + if(p->GetNextDestination() == -1 || p->ChangedSubRoom()) { + //execute periodical sensors + sensor_manager->execute(p, SensorManager::PERIODIC); + + //check if there is a way to the outside the pedestrian knows (in the cognitive map) + const NavLine * destination = NULL; + destination = (*cm_storage)[p]->GetDestination(); + if(destination == NULL) { + //no destination was found, now we could start the discovery! + //1. run the no_way sensors for room discovery. + sensor_manager->execute(p, SensorManager::NO_WAY); + + //check if this was enough for finding a global path to the exit + destination = (*cm_storage)[p]->GetDestination(); + + if(destination == NULL) { + //we still do not have a way. lets take the "best" local edge + //for this we don't calculate the cost to exit but calculte the cost for the edges at the actual vertex. + destination = (*cm_storage)[p]->GetLocalDestination(); + } + } + + //if we still could not found any destination we are lost! Pedestrian will be deleted + //no destination should just appear in bug case or closed rooms. + if(destination == NULL) { + Log->Write("ERROR: \t One Pedestrian (ID: %i) was not able to find any destination", p->GetID()); + return -1; + } + + p->SetExitLine(destination); + p->SetExitIndex(destination->GetUniqueID()); + } + return 1; } void CognitiveMapRouter::CheckAndInitPedestrian(Pedestrian * p) { - //check for former goal. - if(p->GetLastDestination() == -1) { - //no former goal. so initial route has to be choosen - //this is needed for initialisation - p->ChangedSubRoom(); - sensor_manager->execute(p, SensorManager::INIT); - } + //check for former goal. + if(p->GetLastDestination() == -1) { + //no former goal. so initial route has to be choosen + //this is needed for initialisation + p->ChangedSubRoom(); + sensor_manager->execute(p, SensorManager::INIT); + } } void CognitiveMapRouter::Init(Building * b) { - Log->Write("INFO:\tInit the Cognitive Map Router Engine"); - building = b; - - //Init Cognitive Map Storage - cm_storage = new CognitiveMapStorage(building); - Log->Write("INFO:\tInitialized CognitiveMapStorage"); - //Init Sensor Manager - sensor_manager = SensorManager::InitWithAllSensors(b, cm_storage); - Log->Write("INFO:\tInitialized SensorManager"); + Log->Write("INFO:\tInit the Cognitive Map Router Engine"); + building = b; + + //Init Cognitive Map Storage + cm_storage = new CognitiveMapStorage(building); + Log->Write("INFO:\tInitialized CognitiveMapStorage"); + //Init Sensor Manager + sensor_manager = SensorManager::InitWithAllSensors(b, cm_storage); + Log->Write("INFO:\tInitialized SensorManager"); } diff --git a/routing/CognitiveMapRouter.h b/routing/CognitiveMapRouter.h index ef372d280fb7b9d062cf8e2c101cdfdf1695ae77..cfbf8b486d9b90877b99494cca2aa3eee0242967 100644 --- a/routing/CognitiveMapRouter.h +++ b/routing/CognitiveMapRouter.h @@ -25,20 +25,20 @@ class SensorManager; */ class CognitiveMapRouter: public Router { - public: - CognitiveMapRouter(); - virtual ~CognitiveMapRouter(); +public: + CognitiveMapRouter(); + virtual ~CognitiveMapRouter(); - virtual int FindExit(Pedestrian* p); - virtual void Init(Building* b); + virtual int FindExit(Pedestrian* p); + virtual void Init(Building* b); - protected: - void CheckAndInitPedestrian(Pedestrian *); - private: +protected: + void CheckAndInitPedestrian(Pedestrian *); +private: - Building * building; - CognitiveMapStorage * cm_storage; - SensorManager * sensor_manager; + Building * building; + CognitiveMapStorage * cm_storage; + SensorManager * sensor_manager; }; diff --git a/routing/ConvexDecomp.h b/routing/ConvexDecomp.h index a16d0bcb491d4c68a7a8ad42abbeaaa84330eeee..92a80cfe8a38d1ef643ff9d1d2157640d7941947 100644 --- a/routing/ConvexDecomp.h +++ b/routing/ConvexDecomp.h @@ -44,14 +44,13 @@ #include <CGAL/centroid.h> -struct FaceInfo2 -{ - FaceInfo2(){} - int nesting_level; +struct FaceInfo2 { + FaceInfo2() {} + int nesting_level; - bool in_domain(){ - return nesting_level%2 == 1; - } + bool in_domain() { + return nesting_level%2 == 1; + } }; @@ -112,27 +111,27 @@ mark_domains(CDT& ct, int index, std::list<CDT::Edge>& border ) { - if(start->info().nesting_level != -1){ - return; - } - std::list<CDT::Face_handle> queue; - queue.push_back(start); - - while(! queue.empty()){ - CDT::Face_handle fh = queue.front(); - queue.pop_front(); - if(fh->info().nesting_level == -1){ - fh->info().nesting_level = index; - for(int i = 0; i < 3; i++){ - CDT::Edge e(fh,i); - CDT::Face_handle n = fh->neighbor(i); - if(n->info().nesting_level == -1){ - if(ct.is_constrained(e)) border.push_back(e); - else queue.push_back(n); - } - } - } - } + if(start->info().nesting_level != -1) { + return; + } + std::list<CDT::Face_handle> queue; + queue.push_back(start); + + while(! queue.empty()) { + CDT::Face_handle fh = queue.front(); + queue.pop_front(); + if(fh->info().nesting_level == -1) { + fh->info().nesting_level = index; + for(int i = 0; i < 3; i++) { + CDT::Edge e(fh,i); + CDT::Face_handle n = fh->neighbor(i); + if(n->info().nesting_level == -1) { + if(ct.is_constrained(e)) border.push_back(e); + else queue.push_back(n); + } + } + } + } } //explore set of facets connected with non constrained edges, @@ -145,160 +144,157 @@ inline void mark_domains(CDT& cdt) { - for(CDT::All_faces_iterator it = cdt.all_faces_begin(); it != cdt.all_faces_end(); ++it){ - it->info().nesting_level = -1; - } - - int index = 0; - std::list<CDT::Edge> border; - mark_domains(cdt, cdt.infinite_face(), index++, border); - while(! border.empty()){ - CDT::Edge e = border.front(); - border.pop_front(); - CDT::Face_handle n = e.first->neighbor(e.second); - if(n->info().nesting_level == -1){ - mark_domains(cdt, n, e.first->info().nesting_level+1, border); - } - } + for(CDT::All_faces_iterator it = cdt.all_faces_begin(); it != cdt.all_faces_end(); ++it) { + it->info().nesting_level = -1; + } + + int index = 0; + std::list<CDT::Edge> border; + mark_domains(cdt, cdt.infinite_face(), index++, border); + while(! border.empty()) { + CDT::Edge e = border.front(); + border.pop_front(); + CDT::Face_handle n = e.first->neighbor(e.second); + if(n->info().nesting_level == -1) { + mark_domains(cdt, n, e.first->info().nesting_level+1, border); + } + } } inline -void insert_polygon(CDT& cdt,const Polygon_2& polygon){ - if ( polygon.is_empty() ) return; - CDT::Vertex_handle v_prev=cdt.insert(*CGAL::cpp0x::prev(polygon.vertices_end())); - for (Polygon_2::Vertex_iterator vit=polygon.vertices_begin(); - vit!=polygon.vertices_end();++vit) - { - CDT::Vertex_handle vh=cdt.insert(*vit); - cdt.insert_constraint(vh,v_prev); - v_prev=vh; - } +void insert_polygon(CDT& cdt,const Polygon_2& polygon) +{ + if ( polygon.is_empty() ) return; + CDT::Vertex_handle v_prev=cdt.insert(*CGAL::cpp0x::prev(polygon.vertices_end())); + for (Polygon_2::Vertex_iterator vit=polygon.vertices_begin(); + vit!=polygon.vertices_end(); ++vit) { + CDT::Vertex_handle vh=cdt.insert(*vit); + cdt.insert_constraint(vh,v_prev); + v_prev=vh; + } } inline int test_triangulation( ) { - //construct two non-intersecting nested polygons - Polygon_2 polygon1; - polygon1.push_back(Point_2(0,0)); - polygon1.push_back(Point_2(2,0)); - polygon1.push_back(Point_2(2,2)); - polygon1.push_back(Point_2(0,2)); - Polygon_2 polygon2; - polygon2.push_back(Point_2(0.5,0.5)); - polygon2.push_back(Point_2(1.5,0.5)); - polygon2.push_back(Point_2(1.5,1.5)); - polygon2.push_back(Point_2(0.5,1.5)); - - //Insert the polyons into a constrained triangulation - CDT cdt; - insert_polygon(cdt,polygon1); - insert_polygon(cdt,polygon2); - - //Mark facets that are inside the domain bounded by the polygon - mark_domains(cdt); - - int count=0; - for (CDT::Finite_faces_iterator fit=cdt.finite_faces_begin(); - fit!=cdt.finite_faces_end();++fit) - { - if ( fit->info().in_domain() ) ++count; - } - - //cdt.draw_triangulation(std::cout); - std::cout << "There are " << count << " facets in the domain." << std::endl; - - - CGAL::Geomview_stream gv(CGAL::Bbox_3(-100, -100, -100, 100, 100, 100)); - gv.set_line_width(4); - gv.set_trace(true); - gv.set_bg_color(CGAL::Color(0, 200, 200)); - // gv.clear(); - - // use different colors, and put a few sleeps/clear. - //gv << CGAL::BLUE; - //gv.set_wired(true); - - - CDT::Finite_faces_iterator it; - for (it = cdt.finite_faces_begin(); it != cdt.finite_faces_end(); it++) - { - std::cout << cdt.triangle(it) << std::endl; - gv << cdt.triangle(it) ; - } - - return 0; + //construct two non-intersecting nested polygons + Polygon_2 polygon1; + polygon1.push_back(Point_2(0,0)); + polygon1.push_back(Point_2(2,0)); + polygon1.push_back(Point_2(2,2)); + polygon1.push_back(Point_2(0,2)); + Polygon_2 polygon2; + polygon2.push_back(Point_2(0.5,0.5)); + polygon2.push_back(Point_2(1.5,0.5)); + polygon2.push_back(Point_2(1.5,1.5)); + polygon2.push_back(Point_2(0.5,1.5)); + + //Insert the polyons into a constrained triangulation + CDT cdt; + insert_polygon(cdt,polygon1); + insert_polygon(cdt,polygon2); + + //Mark facets that are inside the domain bounded by the polygon + mark_domains(cdt); + + int count=0; + for (CDT::Finite_faces_iterator fit=cdt.finite_faces_begin(); + fit!=cdt.finite_faces_end(); ++fit) { + if ( fit->info().in_domain() ) ++count; + } + + //cdt.draw_triangulation(std::cout); + std::cout << "There are " << count << " facets in the domain." << std::endl; + + + CGAL::Geomview_stream gv(CGAL::Bbox_3(-100, -100, -100, 100, 100, 100)); + gv.set_line_width(4); + gv.set_trace(true); + gv.set_bg_color(CGAL::Color(0, 200, 200)); + // gv.clear(); + + // use different colors, and put a few sleeps/clear. + //gv << CGAL::BLUE; + //gv.set_wired(true); + + + CDT::Finite_faces_iterator it; + for (it = cdt.finite_faces_begin(); it != cdt.finite_faces_end(); it++) { + std::cout << cdt.triangle(it) << std::endl; + gv << cdt.triangle(it) ; + } + + return 0; } inline int test_alpha_shape() { - std::list<Point_2> lp; + std::list<Point_2> lp; - lp.push_back(Point_2(0.5,0.5)); - lp.push_back(Point_2(1.5,0.5)); - lp.push_back(Point_2(1.5,1.5)); - lp.push_back(Point_2(0.5,1.5)); + lp.push_back(Point_2(0.5,0.5)); + lp.push_back(Point_2(1.5,0.5)); + lp.push_back(Point_2(1.5,1.5)); + lp.push_back(Point_2(0.5,1.5)); - // compute alpha shape - Alpha_shape_2 as(lp.begin(),lp.end()); - std::cout << "Alpha shape computed in REGULARIZED mode by default" - << std::endl; + // compute alpha shape + Alpha_shape_2 as(lp.begin(),lp.end()); + std::cout << "Alpha shape computed in REGULARIZED mode by default" + << std::endl; - std::list<Point_2> env=as.Output(); - std::cout <<"size: " <<env.size()<<std::endl; - getc(stdin); + std::list<Point_2> env=as.Output(); + std::cout <<"size: " <<env.size()<<std::endl; + getc(stdin); - for (std::list<Point_2>::const_iterator iterator = env.begin(), end = env.end(); iterator != end; ++iterator) { - std::cout << *iterator; - } + for (std::list<Point_2>::const_iterator iterator = env.begin(), end = env.end(); iterator != end; ++iterator) { + std::cout << *iterator; + } - // for (Alpha_vertex_iterator vit = as.Alpha_shape_vertices_begin(); - // vit != as.alpha_shape_vertices_end(); ++vit) { - // - // } + // for (Alpha_vertex_iterator vit = as.Alpha_shape_vertices_begin(); + // vit != as.alpha_shape_vertices_end(); ++vit) { + // + // } - // find optimal alpha value - Alpha_iterator opt = as.find_optimal_alpha(1); - std::cout << "Optimal alpha value to get one connected component is " - << *opt << std::endl; - as.set_alpha(*opt); - assert(as.number_of_solid_components() == 1); - return 0; + // find optimal alpha value + Alpha_iterator opt = as.find_optimal_alpha(1); + std::cout << "Optimal alpha value to get one connected component is " + << *opt << std::endl; + as.set_alpha(*opt); + assert(as.number_of_solid_components() == 1); + return 0; } template<class Kernel, class Container> - void print_polygon (const CGAL::Polygon_2<Kernel, Container>& P) +void print_polygon (const CGAL::Polygon_2<Kernel, Container>& P) { - typename CGAL::Polygon_2<Kernel, Container>::Vertex_const_iterator vit; + typename CGAL::Polygon_2<Kernel, Container>::Vertex_const_iterator vit; - std::cout << "[ " << P.size() << " vertices:"; - for (vit = P.vertices_begin(); vit != P.vertices_end(); ++vit) - std::cout << " (" << *vit << ')'; - std::cout << " ]" << std::endl; + std::cout << "[ " << P.size() << " vertices:"; + for (vit = P.vertices_begin(); vit != P.vertices_end(); ++vit) + std::cout << " (" << *vit << ')'; + std::cout << " ]" << std::endl; } template<class Kernel, class Container> - void print_polygon_with_holes(const CGAL::Polygon_with_holes_2<Kernel, Container> & pwh) +void print_polygon_with_holes(const CGAL::Polygon_with_holes_2<Kernel, Container> & pwh) { - if (! pwh.is_unbounded()) { - std::cout << "{ Outer boundary = "; - print_polygon (pwh.outer_boundary()); - } - else - std::cout << "{ Unbounded polygon." << std::endl; - - typename CGAL::Polygon_with_holes_2<Kernel,Container>::Hole_const_iterator hit; - unsigned int k = 1; - - std::cout << " " << pwh.number_of_holes() << " holes:" << std::endl; - for (hit = pwh.holes_begin(); hit != pwh.holes_end(); ++hit, ++k) { - std::cout << " Hole #" << k << " = "; - print_polygon (*hit); - } - std::cout << " }" << std::endl; + if (! pwh.is_unbounded()) { + std::cout << "{ Outer boundary = "; + print_polygon (pwh.outer_boundary()); + } else + std::cout << "{ Unbounded polygon." << std::endl; + + typename CGAL::Polygon_with_holes_2<Kernel,Container>::Hole_const_iterator hit; + unsigned int k = 1; + + std::cout << " " << pwh.number_of_holes() << " holes:" << std::endl; + for (hit = pwh.holes_begin(); hit != pwh.holes_end(); ++hit, ++k) { + std::cout << " Hole #" << k << " = "; + print_polygon (*hit); + } + std::cout << " }" << std::endl; } #endif /* _CGAL */ #endif /* _GEOMETRY_FUNCTIONS_ */ diff --git a/routing/DTriangulation.cpp b/routing/DTriangulation.cpp index 35478e941654167c000bc4151aefd83f33b3bd7f..891e497c755e8fe66991b35df964c10765fcc46a 100644 --- a/routing/DTriangulation.cpp +++ b/routing/DTriangulation.cpp @@ -9,44 +9,49 @@ using namespace std; -DTriangulation::DTriangulation() { - _cdt=NULL; +DTriangulation::DTriangulation() +{ + _cdt=NULL; } -DTriangulation::~DTriangulation() { +DTriangulation::~DTriangulation() +{ - for(unsigned int i = 0; i < _holesPolylines.size(); i++) { - vector<p2t::Point*> poly = _holesPolylines[i]; - FreeClear(poly); - } + for(unsigned int i = 0; i < _holesPolylines.size(); i++) { + vector<p2t::Point*> poly = _holesPolylines[i]; + FreeClear(poly); + } - FreeClear(_outerConstraintsPolyline); - delete _cdt; + FreeClear(_outerConstraintsPolyline); + delete _cdt; } -void DTriangulation::Triangulate() { +void DTriangulation::Triangulate() +{ - _cdt= new p2t::CDT(_outerConstraintsPolyline); + _cdt= new p2t::CDT(_outerConstraintsPolyline); - for(unsigned int h=0;h<_holesPolylines.size();h++){ - _cdt->AddHole(_holesPolylines[h]); - } - _cdt->Triangulate(); + for(unsigned int h=0; h<_holesPolylines.size(); h++) { + _cdt->AddHole(_holesPolylines[h]); + } + _cdt->Triangulate(); } -void DTriangulation::SetOuterPolygone(const std::vector<Point>& outPoly) { +void DTriangulation::SetOuterPolygone(const std::vector<Point>& outPoly) +{ - for(unsigned int i=0;i<outPoly.size();i++){ - _outerConstraintsPolyline.push_back(new p2t::Point(outPoly[i]._x,outPoly[i]._y)); - } + for(unsigned int i=0; i<outPoly.size(); i++) { + _outerConstraintsPolyline.push_back(new p2t::Point(outPoly[i]._x,outPoly[i]._y)); + } } -void DTriangulation::AddHole(const std::vector<Point>& hole) { +void DTriangulation::AddHole(const std::vector<Point>& hole) +{ - std::vector<p2t::Point*> newHole; + std::vector<p2t::Point*> newHole; - for(unsigned int i=0;i<hole.size();i++){ - newHole.push_back(new p2t::Point(hole[i]._x,hole[i]._y)); - } - _holesPolylines.push_back(newHole); + for(unsigned int i=0; i<hole.size(); i++) { + newHole.push_back(new p2t::Point(hole[i]._x,hole[i]._y)); + } + _holesPolylines.push_back(newHole); } diff --git a/routing/DTriangulation.h b/routing/DTriangulation.h index b1c0ef83547577f8140904db553d8bc9d660c0a8..92dd52c118c4f590efa26408a5f30d6fac793ff2 100644 --- a/routing/DTriangulation.h +++ b/routing/DTriangulation.h @@ -43,51 +43,51 @@ class DTriangulation { - public: - DTriangulation(); +public: + DTriangulation(); - virtual ~DTriangulation(); + virtual ~DTriangulation(); - /** - * Triangulate the specified domain - * \see SetOuterPolygone - * \see AddHole - */ - void Triangulate(); + /** + * Triangulate the specified domain + * \see SetOuterPolygone + * \see AddHole + */ + void Triangulate(); - /** - * @return the triangles resulting from the triangulation - */ - std::vector<p2t::Triangle*> GetTriangles(){ - return _cdt->GetTriangles(); - } + /** + * @return the triangles resulting from the triangulation + */ + std::vector<p2t::Triangle*> GetTriangles() { + return _cdt->GetTriangles(); + } - /** - * Set the boundaries of the domain - * @param outerConstraints - */ - void SetOuterPolygone(const std::vector<Point>& outerConstraints); + /** + * Set the boundaries of the domain + * @param outerConstraints + */ + void SetOuterPolygone(const std::vector<Point>& outerConstraints); - /** - * Add a new hole - * A domain can contains holes. - * They should fully be inside the domain. - */ - void AddHole(const std::vector<Point>& hole); + /** + * Add a new hole + * A domain can contains holes. + * They should fully be inside the domain. + */ + void AddHole(const std::vector<Point>& hole); - //templates for freeing and clearing a vector of pointers - template <class C> void FreeClear( C & cntr ) { - for ( typename C::iterator it = cntr.begin(); - it != cntr.end(); ++it ) { - delete * it; - } - cntr.clear(); - } + //templates for freeing and clearing a vector of pointers + template <class C> void FreeClear( C & cntr ) { + for ( typename C::iterator it = cntr.begin(); + it != cntr.end(); ++it ) { + delete * it; + } + cntr.clear(); + } - private: - std::vector< std::vector<p2t::Point*> > _holesPolylines; - std::vector<p2t::Point*> _outerConstraintsPolyline; - p2t::CDT* _cdt; +private: + std::vector< std::vector<p2t::Point*> > _holesPolylines; + std::vector<p2t::Point*> _outerConstraintsPolyline; + p2t::CDT* _cdt; }; diff --git a/routing/DirectionStrategy.cpp b/routing/DirectionStrategy.cpp index a8a9c63d9c58b806e8b253e4c508537ba02255e1..b0a073e7458a31da4c03b995d22251b8e332c634 100644 --- a/routing/DirectionStrategy.cpp +++ b/routing/DirectionStrategy.cpp @@ -29,166 +29,166 @@ #include "../geometry/Room.h" #include "../pedestrian/Pedestrian.h" -DirectionStrategy::DirectionStrategy() { +DirectionStrategy::DirectionStrategy() +{ } -DirectionStrategy::DirectionStrategy(const DirectionStrategy& orig) { +DirectionStrategy::DirectionStrategy(const DirectionStrategy& orig) +{ } -DirectionStrategy::~DirectionStrategy() { +DirectionStrategy::~DirectionStrategy() +{ } //@{ -Point DirectionMiddlePoint::GetTarget(Room* room, Pedestrian* ped) const { - return (ped->GetExitLine()->GetPoint1() + ped->GetExitLine()->GetPoint2())*0.5; +Point DirectionMiddlePoint::GetTarget(Room* room, Pedestrian* ped) const +{ + return (ped->GetExitLine()->GetPoint1() + ped->GetExitLine()->GetPoint2())*0.5; } -Point DirectionMinSeperation::GetTarget(Room* room, Pedestrian* ped) const { - return ped->GetExitLine()->ShortestPoint(ped->GetPos()); +Point DirectionMinSeperation::GetTarget(Room* room, Pedestrian* ped) const +{ + return ped->GetExitLine()->ShortestPoint(ped->GetPos()); } -Point DirectionMinSeperationShorterLine::GetTarget(Room* room, Pedestrian* ped) const { - - double d = 0.2; // beide Seiten um 20 cm verkürzen - - const Point& p1 = ped->GetExitLine()->GetPoint1(); - const Point& p2 = ped->GetExitLine()->GetPoint2(); - Point diff = (p1 - p2).Normalized() * d; - Line e_neu = Line(p1 - diff, p2 + diff); - Point target = e_neu.ShortestPoint(ped->GetPos()); - // if(ped->GetID() == 4) - // { - // printf("X=[%.2f], Y=[%.2f]\n", ped->GetPos().GetX(), ped->GetPos().GetY()); - // printf("p1=[%.2f, %.2f], p2=[%.2f, %.2f]\n", p1.GetX(), p1.GetY(), p2.GetX(), p2.GetY()); - // printf("diff=[%.2f, %.2f]\n", diff.GetX(), diff.GetY()); - // printf("p1-diff=[%.2f, %.2f], p2+diff=[%.2f, %.2f]\n", (p1-diff).GetX(), (p1-diff).GetY(), (p2+diff).GetX(), (p2+diff).GetY() ); - - // printf("target=[%.2f, %.2f]\n", target.GetX(), target.GetY()); - - // } - // kürzester Punkt auf der Linie - - return target; +Point DirectionMinSeperationShorterLine::GetTarget(Room* room, Pedestrian* ped) const +{ + + double d = 0.2; // beide Seiten um 20 cm verkürzen + + const Point& p1 = ped->GetExitLine()->GetPoint1(); + const Point& p2 = ped->GetExitLine()->GetPoint2(); + Point diff = (p1 - p2).Normalized() * d; + Line e_neu = Line(p1 - diff, p2 + diff); + Point target = e_neu.ShortestPoint(ped->GetPos()); + // if(ped->GetID() == 4) + // { + // printf("X=[%.2f], Y=[%.2f]\n", ped->GetPos().GetX(), ped->GetPos().GetY()); + // printf("p1=[%.2f, %.2f], p2=[%.2f, %.2f]\n", p1.GetX(), p1.GetY(), p2.GetX(), p2.GetY()); + // printf("diff=[%.2f, %.2f]\n", diff.GetX(), diff.GetY()); + // printf("p1-diff=[%.2f, %.2f], p2+diff=[%.2f, %.2f]\n", (p1-diff).GetX(), (p1-diff).GetY(), (p2+diff).GetX(), (p2+diff).GetY() ); + + // printf("target=[%.2f, %.2f]\n", target.GetX(), target.GetY()); + + // } + // kürzester Punkt auf der Linie + + return target; } -Point DirectionInRangeBottleneck::GetTarget(Room* room, Pedestrian* ped) const { - const Point& p1 = ped->GetExitLine()->GetPoint1(); - const Point& p2 = ped->GetExitLine()->GetPoint2(); - Line ExitLine = Line(p1, p2); - Point Lot = ExitLine.LotPoint( ped->GetPos() ); - Point ExitMiddle = (p1+p2)*0.5; - double d = 0.05; - Point diff = (p1 - p2).Normalized() * d; - Line e_neu = Line(p1 - diff, p2 + diff); - - - if ( e_neu.IsInLineSegment(Lot) ) - { - return Lot; - } - else - { - return ExitMiddle; - } +Point DirectionInRangeBottleneck::GetTarget(Room* room, Pedestrian* ped) const +{ + const Point& p1 = ped->GetExitLine()->GetPoint1(); + const Point& p2 = ped->GetExitLine()->GetPoint2(); + Line ExitLine = Line(p1, p2); + Point Lot = ExitLine.LotPoint( ped->GetPos() ); + Point ExitMiddle = (p1+p2)*0.5; + double d = 0.05; + Point diff = (p1 - p2).Normalized() * d; + Line e_neu = Line(p1 - diff, p2 + diff); + + + if ( e_neu.IsInLineSegment(Lot) ) { + return Lot; + } else { + return ExitMiddle; + } } -/** +/** * this strategy is designed to work without Hlines for a general geometry. - * First tested for bottlenecks and corners. + * First tested for bottlenecks and corners. * @param room Pointer * @param ped Pointer to Pedestrians - * - * @todo Need more tests e.g. for complex geometries. - * @todo Need refactoring: Put the WALL and OBS loops in appropriate functions + * + * @todo Need more tests e.g. for complex geometries. + * @todo Need refactoring: Put the WALL and OBS loops in appropriate functions * @return Target (Point) - */Point DirectionGeneral::GetTarget(Room* room, Pedestrian* ped) const { -using namespace std; - const Point& p1 = ped->GetExitLine()->GetPoint1(); - const Point& p2 = ped->GetExitLine()->GetPoint2(); - Line ExitLine = Line(p1, p2); - //Point Lot = ExitLine.LotPoint( ped->GetPos() ); - double d = 0.2; //shorten the line by 20 cm - Point diff = (p1 - p2).Normalized() * d; - Line e_neu = Line(p1 - diff, p2 + diff); - - // kürzester Punkt auf der Linie - Point NextPointOnLine = e_neu.ShortestPoint(ped->GetPos()); - - Line tmpDirection = Line(ped->GetPos(), NextPointOnLine );//This direction will be rotated if - //printf("nextPointOn Line: %f %f\n", NextPointOnLine.GetX(), NextPointOnLine.GetY()); + */Point DirectionGeneral::GetTarget(Room* room, Pedestrian* ped) const +{ + using namespace std; + const Point& p1 = ped->GetExitLine()->GetPoint1(); + const Point& p2 = ped->GetExitLine()->GetPoint2(); + Line ExitLine = Line(p1, p2); + //Point Lot = ExitLine.LotPoint( ped->GetPos() ); + double d = 0.2; //shorten the line by 20 cm + Point diff = (p1 - p2).Normalized() * d; + Line e_neu = Line(p1 - diff, p2 + diff); + + // kürzester Punkt auf der Linie + Point NextPointOnLine = e_neu.ShortestPoint(ped->GetPos()); + + Line tmpDirection = Line(ped->GetPos(), NextPointOnLine );//This direction will be rotated if + //printf("nextPointOn Line: %f %f\n", NextPointOnLine.GetX(), NextPointOnLine.GetY()); //it intersect a wall/obstacle. // check for intersection with walls //todo: make a FUNCTION of this - double dist; - int inear = -1; - int iObs = -1; - double minDist = 20001; - int subroomId = ped->GetSubRoomID(); - SubRoom * subroom = room->GetSubRoom(subroomId); - - //============================ WALLS =========================== - const vector<Wall>& walls = subroom->GetAllWalls(); - for (int i = 0; i < subroom->GetNumberOfWalls(); i++) { - dist = tmpDirection.GetIntersectionDistance(walls[i]); - // printf("Check wall %d. Dist = %f (%f)\n", i, dist, minDist); - // printf("%f %f --- %f %f\n===========\n",walls[i].GetPoint1().GetX(),walls[i].GetPoint1().GetY(), walls[i].GetPoint2().GetX(),walls[i].GetPoint2().GetY()); - if (dist < minDist) - { - inear = i; - minDist = dist; - } - }//walls - //============================ WALLS =========================== - - //============================ OBST =========================== - const vector<Obstacle*>& obstacles = subroom->GetAllObstacles(); - for(unsigned int obs=0; obs<obstacles.size(); ++obs){ - const vector<Wall>& owalls = obstacles[obs]->GetAllWalls(); - for (unsigned int i = 0; i < owalls.size(); i++) { - dist = tmpDirection.GetIntersectionDistance(owalls[i]); - printf("Check OBS:obs=%d, i=%d Dist = %f (%f)\n", obs, i, dist, minDist); - if (dist < minDist) - { - inear = i; - minDist = dist; - iObs = obs; - } - }//walls of obstacle - }// obstacles - //============================ OBST =========================== - - - double angle = 0; - if (inear >= 0) - { - if(iObs >= 0) - { - const vector<Wall>& owalls = obstacles[iObs]->GetAllWalls(); - angle = tmpDirection.GetAngle(owalls[inear]); - - } - else - angle = tmpDirection.GetAngle(walls[inear]); - } + double dist; + int inear = -1; + int iObs = -1; + double minDist = 20001; + int subroomId = ped->GetSubRoomID(); + SubRoom * subroom = room->GetSubRoom(subroomId); + + //============================ WALLS =========================== + const vector<Wall>& walls = subroom->GetAllWalls(); + for (int i = 0; i < subroom->GetNumberOfWalls(); i++) { + dist = tmpDirection.GetIntersectionDistance(walls[i]); + // printf("Check wall %d. Dist = %f (%f)\n", i, dist, minDist); + // printf("%f %f --- %f %f\n===========\n",walls[i].GetPoint1().GetX(),walls[i].GetPoint1().GetY(), walls[i].GetPoint2().GetX(),walls[i].GetPoint2().GetY()); + if (dist < minDist) { + inear = i; + minDist = dist; + } + }//walls + //============================ WALLS =========================== + + //============================ OBST =========================== + const vector<Obstacle*>& obstacles = subroom->GetAllObstacles(); + for(unsigned int obs=0; obs<obstacles.size(); ++obs) { + const vector<Wall>& owalls = obstacles[obs]->GetAllWalls(); + for (unsigned int i = 0; i < owalls.size(); i++) { + dist = tmpDirection.GetIntersectionDistance(owalls[i]); + printf("Check OBS:obs=%d, i=%d Dist = %f (%f)\n", obs, i, dist, minDist); + if (dist < minDist) { + inear = i; + minDist = dist; + iObs = obs; + } + }//walls of obstacle + }// obstacles + //============================ OBST =========================== + + + double angle = 0; + if (inear >= 0) { + if(iObs >= 0) { + const vector<Wall>& owalls = obstacles[iObs]->GetAllWalls(); + angle = tmpDirection.GetAngle(owalls[inear]); + + } else + angle = tmpDirection.GetAngle(walls[inear]); + } //////////////////////////////////////////////////////////// -// printf("inear=%d, iObs=%d, minDist=%f\n", inear, iObs, minDist); - Point G; - if (fabs(angle) > J_EPS) - //G = tmpDirection.GetPoint2().Rotate(cos(angle), sin(angle)) ; - G = (NextPointOnLine-ped->GetPos()).Rotate(cos(angle), sin(angle))+ped->GetPos() ; - else - //G = tmpDirection.GetPoint2(); - G = NextPointOnLine; - // printf("PED=%d\n", ped->GetID()); - // printf ("MC Posx = %.2f, Posy=%.2f, Lot=[%.2f, %.2f]\n", ped->GetPos().GetX(), ped->GetPos().GetY(), NextPointOnLine.GetX(), NextPointOnLine.GetY()); - // printf("MC p1=[%.2f, %.2f] p2=[%.2f, %.2f]\n", p1.GetX(), p1.GetY(), p2.GetX(), p2.GetY()); - // printf("angle=%f, G=[%.2f, %.2f]\n", angle, G.GetX(), G.GetY()); - - // fprintf(stderr, "%.2f %.2f %.2f %.2f %f %f %d\n", NextPointOnLine.GetX(), NextPointOnLine.GetY(), ped->GetPos().GetX(), ped->GetPos().GetY(), G.GetX(), G.GetY(), ped->GetID()); - - //if(angle) - // getc(stdin); - return G; +// printf("inear=%d, iObs=%d, minDist=%f\n", inear, iObs, minDist); + Point G; + if (fabs(angle) > J_EPS) + //G = tmpDirection.GetPoint2().Rotate(cos(angle), sin(angle)) ; + G = (NextPointOnLine-ped->GetPos()).Rotate(cos(angle), sin(angle))+ped->GetPos() ; + else + //G = tmpDirection.GetPoint2(); + G = NextPointOnLine; + // printf("PED=%d\n", ped->GetID()); + // printf ("MC Posx = %.2f, Posy=%.2f, Lot=[%.2f, %.2f]\n", ped->GetPos().GetX(), ped->GetPos().GetY(), NextPointOnLine.GetX(), NextPointOnLine.GetY()); + // printf("MC p1=[%.2f, %.2f] p2=[%.2f, %.2f]\n", p1.GetX(), p1.GetY(), p2.GetX(), p2.GetY()); + // printf("angle=%f, G=[%.2f, %.2f]\n", angle, G.GetX(), G.GetY()); + + // fprintf(stderr, "%.2f %.2f %.2f %.2f %f %f %d\n", NextPointOnLine.GetX(), NextPointOnLine.GetY(), ped->GetPos().GetX(), ped->GetPos().GetY(), G.GetX(), G.GetY(), ped->GetID()); + + //if(angle) + // getc(stdin); + return G; } diff --git a/routing/DirectionStrategy.h b/routing/DirectionStrategy.h index 122abad11e0f3219e7e97e304ac762c3398bb796..2e01b855c2e473e52347309210dca1482891b52e 100644 --- a/routing/DirectionStrategy.h +++ b/routing/DirectionStrategy.h @@ -34,42 +34,37 @@ class Point; class DirectionStrategy { - public: - DirectionStrategy(); - DirectionStrategy(const DirectionStrategy& orig); - virtual ~DirectionStrategy(); - virtual Point GetTarget(Room* room, Pedestrian* ped) const = 0; +public: + DirectionStrategy(); + DirectionStrategy(const DirectionStrategy& orig); + virtual ~DirectionStrategy(); + virtual Point GetTarget(Room* room, Pedestrian* ped) const = 0; }; -class DirectionMiddlePoint : public DirectionStrategy -{ - public: - virtual Point GetTarget(Room* room, Pedestrian* ped) const; +class DirectionMiddlePoint : public DirectionStrategy { +public: + virtual Point GetTarget(Room* room, Pedestrian* ped) const; }; -class DirectionMinSeperation : public DirectionStrategy -{ - public: - virtual Point GetTarget(Room* room, Pedestrian* ped) const; +class DirectionMinSeperation : public DirectionStrategy { +public: + virtual Point GetTarget(Room* room, Pedestrian* ped) const; }; -class DirectionMinSeperationShorterLine : public DirectionStrategy -{ - public: - virtual Point GetTarget(Room* room, Pedestrian* ped) const; +class DirectionMinSeperationShorterLine : public DirectionStrategy { +public: + virtual Point GetTarget(Room* room, Pedestrian* ped) const; }; -class DirectionInRangeBottleneck : public DirectionStrategy -{ - public: - virtual Point GetTarget(Room* room, Pedestrian* ped) const; +class DirectionInRangeBottleneck : public DirectionStrategy { +public: + virtual Point GetTarget(Room* room, Pedestrian* ped) const; }; -class DirectionGeneral : public DirectionStrategy -{ - public: - virtual Point GetTarget(Room* room, Pedestrian* ped) const; +class DirectionGeneral : public DirectionStrategy { +public: + virtual Point GetTarget(Room* room, Pedestrian* ped) const; }; #endif /* _DIRECTIONSTRATEGY_H */ diff --git a/routing/DummyRouter.cpp b/routing/DummyRouter.cpp index 18ff7c1f3efa80955f8567837bfd9277e6a41ae8..bf570dbb2b0f60626b9e6258c228d55e9d65cdd4 100644 --- a/routing/DummyRouter.cpp +++ b/routing/DummyRouter.cpp @@ -9,25 +9,29 @@ #include "../geometry/Building.h" #include "../pedestrian/Pedestrian.h" -DummyRouter::DummyRouter() { - _building=NULL; +DummyRouter::DummyRouter() +{ + _building=NULL; } -DummyRouter::~DummyRouter() { +DummyRouter::~DummyRouter() +{ } -int DummyRouter::FindExit(Pedestrian* p) { - p->SetExitIndex(1); - //p->SetExitLine(_building->getGetCrossing(0)); - return 1; +int DummyRouter::FindExit(Pedestrian* p) +{ + p->SetExitIndex(1); + //p->SetExitLine(_building->getGetCrossing(0)); + return 1; } -void DummyRouter::Init(Building* b) { - _building=b; - Log->Write("ERROR: \tdo not use this <<Dummy>> router !!"); +void DummyRouter::Init(Building* b) +{ + _building=b; + Log->Write("ERROR: \tdo not use this <<Dummy>> router !!"); - //dump all navigation lines + //dump all navigation lines // cout<<"crossing:"<<endl; // for (map<int, Crossing*>::const_iterator iter = pCrossings.begin(); diff --git a/routing/DummyRouter.h b/routing/DummyRouter.h index 88b6aa266fc3cd46db0ff5cebc20db7caa199cb4..ec22a423907652a264315b200af3ffa729449d5b 100644 --- a/routing/DummyRouter.h +++ b/routing/DummyRouter.h @@ -11,14 +11,14 @@ #include "Router.h" class DummyRouter: public Router { - private: - Building* _building; - public: - DummyRouter(); - virtual ~DummyRouter(); +private: + Building* _building; +public: + DummyRouter(); + virtual ~DummyRouter(); - virtual int FindExit(Pedestrian* p); - virtual void Init(Building* b); + virtual int FindExit(Pedestrian* p); + virtual void Init(Building* b); }; diff --git a/routing/GlobalRouter.cpp b/routing/GlobalRouter.cpp index cb4042f53c66d323f68c3d38a43ea8abb888dd00..93aee4517314da5d4f8053889f8829662818d4e8 100644 --- a/routing/GlobalRouter.cpp +++ b/routing/GlobalRouter.cpp @@ -46,487 +46,492 @@ using namespace std; GlobalRouter::GlobalRouter() : - Router() { - _accessPoints = map<int, AccessPoint*>(); - _map_id_to_index = std::map<int, int>(); - _map_index_to_id = std::map<int, int>(); - _distMatrix = NULL; - _pathsMatrix = NULL; - _building = NULL; + Router() +{ + _accessPoints = map<int, AccessPoint*>(); + _map_id_to_index = std::map<int, int>(); + _map_index_to_id = std::map<int, int>(); + _distMatrix = NULL; + _pathsMatrix = NULL; + _building = NULL; } -GlobalRouter::~GlobalRouter() { - - if (_distMatrix && _pathsMatrix) { - const int exitsCnt = _building->GetNumberOfGoals(); - for (int p = 0; p < exitsCnt; ++p) { - delete[] _distMatrix[p]; - delete[] _pathsMatrix[p]; - } - - delete[] _distMatrix; - delete[] _pathsMatrix; - } - - map<int, AccessPoint*>::const_iterator itr; - for (itr = _accessPoints.begin(); itr != _accessPoints.end(); ++itr) { - delete itr->second; - } - _accessPoints.clear(); +GlobalRouter::~GlobalRouter() +{ + + if (_distMatrix && _pathsMatrix) { + const int exitsCnt = _building->GetNumberOfGoals(); + for (int p = 0; p < exitsCnt; ++p) { + delete[] _distMatrix[p]; + delete[] _pathsMatrix[p]; + } + + delete[] _distMatrix; + delete[] _pathsMatrix; + } + + map<int, AccessPoint*>::const_iterator itr; + for (itr = _accessPoints.begin(); itr != _accessPoints.end(); ++itr) { + delete itr->second; + } + _accessPoints.clear(); } -void GlobalRouter::Init(Building* building) { - - Log->Write("INFO:\tInit the Global Router Engine"); - _building = building; - LoadRoutingInfos(GetRoutingInfoFile()); - - // initialize the distances matrix for the floydwahrshall - - const int exitsCnt = _building->GetNumberOfGoals() + _building->GetAllGoals().size(); - - _distMatrix = new double*[exitsCnt]; - _pathsMatrix = new int*[exitsCnt]; - - for (int i = 0; i < exitsCnt; ++i) { - _distMatrix[i] = new double[exitsCnt]; - _pathsMatrix[i] = new int[exitsCnt]; - } - // initializing the values - // all nodes are disconnected - for (int p = 0; p < exitsCnt; ++p){ - for (int r = 0; r < exitsCnt; ++r) { - _distMatrix[p][r] = (r == p) ? 0.0 : FLT_MAX;/*0.0*/ - _pathsMatrix[p][r] = p;/*0.0*/ - } - } - - // init the access points - int index = 0; - - for (map<int, Hline*>::const_iterator itr = _building->GetAllHlines().begin(); - itr != _building->GetAllHlines().end(); ++itr) { - //int door=itr->first; - int door = itr->second->GetUniqueID(); - Hline* cross = itr->second; - Point centre = cross->GetCentre(); - double center[2] = { centre.GetX(), centre.GetY() }; - - AccessPoint* ap = new AccessPoint(door, center); - ap->SetNavLine(cross); - char friendlyName[CLENGTH]; - sprintf(friendlyName, "hline_%d_room_%d_subroom_%d", cross->GetID(), - cross->GetRoom()->GetID(), - cross->GetSubRoom()->GetSubRoomID()); - ap->SetFriendlyName(friendlyName); - - // save the connecting sub/rooms IDs - int id1 = -1; - if (cross->GetSubRoom()) { - id1 = cross->GetSubRoom()->GetUID(); - } - - ap->setConnectingRooms(id1, id1); - _accessPoints[door] = ap; - - //very nasty - _map_id_to_index[door] = index; - _map_index_to_id[index] = door; - index++; - } - - - for (map<int, Crossing*>::const_iterator itr = _building->GetAllCrossings().begin(); - itr != _building->GetAllCrossings().end(); ++itr) { - - int door = itr->second->GetUniqueID(); - Crossing* cross = itr->second; - const Point& centre = cross->GetCentre(); - double center[2] = { centre.GetX(), centre.GetY() }; - - AccessPoint* ap = new AccessPoint(door, center); - ap->SetNavLine(cross); - char friendlyName[CLENGTH]; - sprintf(friendlyName, "cross_%d_room_%d_subroom_%d", cross->GetID(), - cross->GetRoom1()->GetID(), - cross->GetSubRoom1()->GetSubRoomID()); - ap->SetFriendlyName(friendlyName); - - // save the connecting sub/rooms IDs - int id1 = -1; - if (cross->GetSubRoom1()) { - id1 = cross->GetSubRoom1()->GetUID(); - } - - int id2 = -1; - if (cross->GetSubRoom2()) { - id2 = cross->GetSubRoom2()->GetUID(); - } - - ap->setConnectingRooms(id1, id2); - _accessPoints[door] = ap; - - //very nasty - _map_id_to_index[door] = index; - _map_index_to_id[index] = door; - index++; - } - - for (map<int, Transition*>::const_iterator itr = _building->GetAllTransitions().begin(); - itr != _building->GetAllTransitions().end(); ++itr) { - - int door = itr->second->GetUniqueID(); - Transition* cross = itr->second; - const Point& centre = cross->GetCentre(); - double center[2] = { centre.GetX(), centre.GetY() }; - - AccessPoint* ap = new AccessPoint(door, center); - ap->SetNavLine(cross); - char friendlyName[CLENGTH]; - sprintf(friendlyName, "trans_%d_room_%d_subroom_%d", cross->GetID(), - cross->GetRoom1()->GetID(), - cross->GetSubRoom1()->GetSubRoomID()); - ap->SetFriendlyName(friendlyName); - - ap->SetClosed(!cross->IsOpen()); - // save the connecting sub/rooms IDs - int id1 = -1; - if (cross->GetSubRoom1()) { - id1 = cross->GetSubRoom1()->GetUID(); - } - - int id2 = -1; - if (cross->GetSubRoom2()) { - id2 = cross->GetSubRoom2()->GetUID(); - } - - ap->setConnectingRooms(id1, id2); - _accessPoints[door] = ap; - - //set the final destination - if (cross->IsExit() && cross->IsOpen()) { - ap->SetFinalExitToOutside(true); - Log->Write("INFO: \tExit to outside found: %d [%s]",ap->GetID(),ap->GetFriendlyName().c_str()); - } else if ((id1 == -1) && (id2 == -1)) { - Log->Write(" a final destination outside the geometry was found"); - ap->SetFinalExitToOutside(true); - } else if (cross->GetRoom1()->GetCaption() == "outside") { - ap->SetFinalExitToOutside(true); - } - - //very nasty - _map_id_to_index[door] = index; - _map_index_to_id[index] = door; - index++; - } - - // loop over the rooms - // loop over the subrooms - // get the transitions in the subrooms - // and compute the distances - - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* room = _building->GetRoom(i); - - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - - SubRoom* sub = room->GetSubRoom(j); - - - // The penalty factor should discourage pedestrians to evacuation through rooms. - double penalty=1.0; - if((sub->GetType()!="floor") && (sub->GetType()!="dA") ) { - penalty=PENALTY_FACTOR; - } - - - //collect all navigation objects - vector<NavLine*> allGoals; - const vector<Crossing*>& crossings = sub->GetAllCrossings(); - allGoals.insert(allGoals.end(), crossings.begin(), crossings.end()); - const vector<Transition*>& transitions = sub->GetAllTransitions(); - allGoals.insert(allGoals.end(), transitions.begin(), - transitions.end()); - const vector<Hline*>& hlines = sub->GetAllHlines(); - allGoals.insert(allGoals.end(), hlines.begin(), hlines.end()); - - //process the hlines - //process the crossings - //process the transitions - for (unsigned int n1 = 0; n1 < allGoals.size(); n1++) { - - NavLine* nav1 = allGoals[n1]; - AccessPoint* from_AP = _accessPoints[nav1->GetUniqueID()]; - int from_door = _map_id_to_index[nav1->GetUniqueID()]; - if(from_AP->IsClosed()) continue; - - for (unsigned int n2 = 0; n2 < allGoals.size(); n2++) { - NavLine* nav2 = allGoals[n2]; - AccessPoint* to_AP = _accessPoints[nav2->GetUniqueID()]; - if(to_AP->IsClosed()) continue; - - if (n1 == n2) - continue; - if (nav1->operator ==(*nav2)) - continue; - - if (sub->IsVisible(nav1->GetCentre(), nav2->GetCentre(), true)) { - int to_door = _map_id_to_index[nav2->GetUniqueID()]; - _distMatrix[from_door][to_door] = penalty*(nav1->GetCentre() +void GlobalRouter::Init(Building* building) +{ + + Log->Write("INFO:\tInit the Global Router Engine"); + _building = building; + LoadRoutingInfos(GetRoutingInfoFile()); + + // initialize the distances matrix for the floydwahrshall + + const int exitsCnt = _building->GetNumberOfGoals() + _building->GetAllGoals().size(); + + _distMatrix = new double*[exitsCnt]; + _pathsMatrix = new int*[exitsCnt]; + + for (int i = 0; i < exitsCnt; ++i) { + _distMatrix[i] = new double[exitsCnt]; + _pathsMatrix[i] = new int[exitsCnt]; + } + // initializing the values + // all nodes are disconnected + for (int p = 0; p < exitsCnt; ++p) { + for (int r = 0; r < exitsCnt; ++r) { + _distMatrix[p][r] = (r == p) ? 0.0 : FLT_MAX;/*0.0*/ + _pathsMatrix[p][r] = p;/*0.0*/ + } + } + + // init the access points + int index = 0; + + for (map<int, Hline*>::const_iterator itr = _building->GetAllHlines().begin(); + itr != _building->GetAllHlines().end(); ++itr) { + //int door=itr->first; + int door = itr->second->GetUniqueID(); + Hline* cross = itr->second; + Point centre = cross->GetCentre(); + double center[2] = { centre.GetX(), centre.GetY() }; + + AccessPoint* ap = new AccessPoint(door, center); + ap->SetNavLine(cross); + char friendlyName[CLENGTH]; + sprintf(friendlyName, "hline_%d_room_%d_subroom_%d", cross->GetID(), + cross->GetRoom()->GetID(), + cross->GetSubRoom()->GetSubRoomID()); + ap->SetFriendlyName(friendlyName); + + // save the connecting sub/rooms IDs + int id1 = -1; + if (cross->GetSubRoom()) { + id1 = cross->GetSubRoom()->GetUID(); + } + + ap->setConnectingRooms(id1, id1); + _accessPoints[door] = ap; + + //very nasty + _map_id_to_index[door] = index; + _map_index_to_id[index] = door; + index++; + } + + + for (map<int, Crossing*>::const_iterator itr = _building->GetAllCrossings().begin(); + itr != _building->GetAllCrossings().end(); ++itr) { + + int door = itr->second->GetUniqueID(); + Crossing* cross = itr->second; + const Point& centre = cross->GetCentre(); + double center[2] = { centre.GetX(), centre.GetY() }; + + AccessPoint* ap = new AccessPoint(door, center); + ap->SetNavLine(cross); + char friendlyName[CLENGTH]; + sprintf(friendlyName, "cross_%d_room_%d_subroom_%d", cross->GetID(), + cross->GetRoom1()->GetID(), + cross->GetSubRoom1()->GetSubRoomID()); + ap->SetFriendlyName(friendlyName); + + // save the connecting sub/rooms IDs + int id1 = -1; + if (cross->GetSubRoom1()) { + id1 = cross->GetSubRoom1()->GetUID(); + } + + int id2 = -1; + if (cross->GetSubRoom2()) { + id2 = cross->GetSubRoom2()->GetUID(); + } + + ap->setConnectingRooms(id1, id2); + _accessPoints[door] = ap; + + //very nasty + _map_id_to_index[door] = index; + _map_index_to_id[index] = door; + index++; + } + + for (map<int, Transition*>::const_iterator itr = _building->GetAllTransitions().begin(); + itr != _building->GetAllTransitions().end(); ++itr) { + + int door = itr->second->GetUniqueID(); + Transition* cross = itr->second; + const Point& centre = cross->GetCentre(); + double center[2] = { centre.GetX(), centre.GetY() }; + + AccessPoint* ap = new AccessPoint(door, center); + ap->SetNavLine(cross); + char friendlyName[CLENGTH]; + sprintf(friendlyName, "trans_%d_room_%d_subroom_%d", cross->GetID(), + cross->GetRoom1()->GetID(), + cross->GetSubRoom1()->GetSubRoomID()); + ap->SetFriendlyName(friendlyName); + + ap->SetClosed(!cross->IsOpen()); + // save the connecting sub/rooms IDs + int id1 = -1; + if (cross->GetSubRoom1()) { + id1 = cross->GetSubRoom1()->GetUID(); + } + + int id2 = -1; + if (cross->GetSubRoom2()) { + id2 = cross->GetSubRoom2()->GetUID(); + } + + ap->setConnectingRooms(id1, id2); + _accessPoints[door] = ap; + + //set the final destination + if (cross->IsExit() && cross->IsOpen()) { + ap->SetFinalExitToOutside(true); + Log->Write("INFO: \tExit to outside found: %d [%s]",ap->GetID(),ap->GetFriendlyName().c_str()); + } else if ((id1 == -1) && (id2 == -1)) { + Log->Write(" a final destination outside the geometry was found"); + ap->SetFinalExitToOutside(true); + } else if (cross->GetRoom1()->GetCaption() == "outside") { + ap->SetFinalExitToOutside(true); + } + + //very nasty + _map_id_to_index[door] = index; + _map_index_to_id[index] = door; + index++; + } + + // loop over the rooms + // loop over the subrooms + // get the transitions in the subrooms + // and compute the distances + + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* room = _building->GetRoom(i); + + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + + SubRoom* sub = room->GetSubRoom(j); + + + // The penalty factor should discourage pedestrians to evacuation through rooms. + double penalty=1.0; + if((sub->GetType()!="floor") && (sub->GetType()!="dA") ) { + penalty=PENALTY_FACTOR; + } + + + //collect all navigation objects + vector<NavLine*> allGoals; + const vector<Crossing*>& crossings = sub->GetAllCrossings(); + allGoals.insert(allGoals.end(), crossings.begin(), crossings.end()); + const vector<Transition*>& transitions = sub->GetAllTransitions(); + allGoals.insert(allGoals.end(), transitions.begin(), + transitions.end()); + const vector<Hline*>& hlines = sub->GetAllHlines(); + allGoals.insert(allGoals.end(), hlines.begin(), hlines.end()); + + //process the hlines + //process the crossings + //process the transitions + for (unsigned int n1 = 0; n1 < allGoals.size(); n1++) { + + NavLine* nav1 = allGoals[n1]; + AccessPoint* from_AP = _accessPoints[nav1->GetUniqueID()]; + int from_door = _map_id_to_index[nav1->GetUniqueID()]; + if(from_AP->IsClosed()) continue; + + for (unsigned int n2 = 0; n2 < allGoals.size(); n2++) { + NavLine* nav2 = allGoals[n2]; + AccessPoint* to_AP = _accessPoints[nav2->GetUniqueID()]; + if(to_AP->IsClosed()) continue; + + if (n1 == n2) + continue; + if (nav1->operator ==(*nav2)) + continue; + + if (sub->IsVisible(nav1->GetCentre(), nav2->GetCentre(), true)) { + int to_door = _map_id_to_index[nav2->GetUniqueID()]; + _distMatrix[from_door][to_door] = penalty*(nav1->GetCentre() - nav2->GetCentre()).Norm(); - from_AP->AddConnectingAP( - _accessPoints[nav2->GetUniqueID()]); - } - } - } - } - } - - //complete the matrix with the final distances between the exits to the outside and the - //final marked goals - - for (unsigned int p = 0; p < _finalDestinations.size(); p++) { - - Goal* goal =_building->GetFinalGoal(_finalDestinations[p]); - const Wall& line=_building->GetFinalGoal(_finalDestinations[p])->GetAllWalls()[0]; - double center[2] = { goal->GetCentroid()._x, goal->GetCentroid()._y }; - - AccessPoint* to_AP = new AccessPoint(line.GetUniqueID(), center); - to_AP->SetFinalGoalOutside(true); - to_AP->SetNavLine(new NavLine(line)); - char friendlyName[CLENGTH]; - sprintf(friendlyName, "finalGoal_%d_located_outside", goal->GetId()); - to_AP->SetFriendlyName(friendlyName); - to_AP->AddFinalDestination(FINAL_DEST_OUT,0.0); - to_AP->AddFinalDestination(goal->GetId(),0.0); - _accessPoints[to_AP->GetID()] = to_AP; - - //very nasty - _map_id_to_index[to_AP->GetID()] = index; - _map_index_to_id[index] = to_AP->GetID(); - index++; - - //only make a connection to final exit to outside - for (map<int, AccessPoint*>::const_iterator itr1 = - _accessPoints.begin(); itr1 != _accessPoints.end(); ++itr1) { - AccessPoint* from_AP = itr1->second; - if(from_AP->GetFinalExitToOutside()==false) continue; - if(from_AP->GetID()==to_AP->GetID()) continue; - from_AP->AddConnectingAP(to_AP); - int from_door= _map_id_to_index[from_AP->GetID()]; - int to_door= _map_id_to_index[to_AP->GetID()]; - // I assume a direct line connection between every exit connected to the outside and - // any final goal also located outside - _distMatrix[from_door][to_door] = PENALTY_FACTOR*from_AP->GetNavLine()->DistTo(goal->GetCentroid()); - - // add a penalty for goals outside due to the direct line assumption while computing the distances - //if (_distMatrix[from_door][to_door] > 10.0) - // _distMatrix[from_door][to_door]*=10; - } - } - - //run the floyd warshall algorithm - FloydWarshall(); - - // set the configuration for reaching the outside - // set the distances to all final APs - - for (map<int, AccessPoint*>::const_iterator itr = _accessPoints.begin(); - itr != _accessPoints.end(); ++itr) { - - AccessPoint* from_AP = itr->second; - int from_door = _map_id_to_index[itr->first]; - if(from_AP->GetFinalGoalOutside()) continue; - //TODO: maybe put the distance to FLT_MAX - if(from_AP->IsClosed()) continue; - - double tmpMinDist = FLT_MAX; - int tmpFinalGlobalNearestID = from_door; - - for (map<int, AccessPoint*>::const_iterator itr1 = - _accessPoints.begin(); itr1 != _accessPoints.end(); ++itr1) { - - AccessPoint* to_AP = itr1->second; - - if(from_AP->GetID()==to_AP->GetID()) continue; - if(from_AP->GetFinalExitToOutside()) continue; - - //if(from_AP->GetFinalGoalOutside()) continue; - - if (to_AP->GetFinalExitToOutside()) { - - int to_door = _map_id_to_index[itr1->first]; - if (from_door == to_door) - continue; - - //cout <<" checking final destination: "<< pAccessPoints[j]->GetID()<<endl; - double dist = _distMatrix[from_door][to_door]; - if (dist < tmpMinDist) { - tmpFinalGlobalNearestID = to_door; - tmpMinDist = dist; - } - } - } - - // in the case it is the final APs - if (tmpFinalGlobalNearestID == from_door) - tmpMinDist = 0.0; - - if (tmpMinDist == FLT_MAX) { - Log->Write( - "ERROR: GlobalRouter: There is no visibility path from [%s] to the outside 1\n", - from_AP->GetFriendlyName().c_str()); - from_AP->Dump(); - exit(EXIT_FAILURE); - } - - // set the distance to the final destination ( OUT ) - from_AP->AddFinalDestination(FINAL_DEST_OUT, tmpMinDist); - - // set the intermediate path to global final destination - GetPath(from_door, tmpFinalGlobalNearestID); - - if (_tmpPedPath.size() >= 2) { - from_AP->AddTransitAPsTo(FINAL_DEST_OUT, + from_AP->AddConnectingAP( + _accessPoints[nav2->GetUniqueID()]); + } + } + } + } + } + + //complete the matrix with the final distances between the exits to the outside and the + //final marked goals + + for (unsigned int p = 0; p < _finalDestinations.size(); p++) { + + Goal* goal =_building->GetFinalGoal(_finalDestinations[p]); + const Wall& line=_building->GetFinalGoal(_finalDestinations[p])->GetAllWalls()[0]; + double center[2] = { goal->GetCentroid()._x, goal->GetCentroid()._y }; + + AccessPoint* to_AP = new AccessPoint(line.GetUniqueID(), center); + to_AP->SetFinalGoalOutside(true); + to_AP->SetNavLine(new NavLine(line)); + char friendlyName[CLENGTH]; + sprintf(friendlyName, "finalGoal_%d_located_outside", goal->GetId()); + to_AP->SetFriendlyName(friendlyName); + to_AP->AddFinalDestination(FINAL_DEST_OUT,0.0); + to_AP->AddFinalDestination(goal->GetId(),0.0); + _accessPoints[to_AP->GetID()] = to_AP; + + //very nasty + _map_id_to_index[to_AP->GetID()] = index; + _map_index_to_id[index] = to_AP->GetID(); + index++; + + //only make a connection to final exit to outside + for (map<int, AccessPoint*>::const_iterator itr1 = + _accessPoints.begin(); itr1 != _accessPoints.end(); ++itr1) { + AccessPoint* from_AP = itr1->second; + if(from_AP->GetFinalExitToOutside()==false) continue; + if(from_AP->GetID()==to_AP->GetID()) continue; + from_AP->AddConnectingAP(to_AP); + int from_door= _map_id_to_index[from_AP->GetID()]; + int to_door= _map_id_to_index[to_AP->GetID()]; + // I assume a direct line connection between every exit connected to the outside and + // any final goal also located outside + _distMatrix[from_door][to_door] = PENALTY_FACTOR*from_AP->GetNavLine()->DistTo(goal->GetCentroid()); + + // add a penalty for goals outside due to the direct line assumption while computing the distances + //if (_distMatrix[from_door][to_door] > 10.0) + // _distMatrix[from_door][to_door]*=10; + } + } + + //run the floyd warshall algorithm + FloydWarshall(); + + // set the configuration for reaching the outside + // set the distances to all final APs + + for (map<int, AccessPoint*>::const_iterator itr = _accessPoints.begin(); + itr != _accessPoints.end(); ++itr) { + + AccessPoint* from_AP = itr->second; + int from_door = _map_id_to_index[itr->first]; + if(from_AP->GetFinalGoalOutside()) continue; + //TODO: maybe put the distance to FLT_MAX + if(from_AP->IsClosed()) continue; + + double tmpMinDist = FLT_MAX; + int tmpFinalGlobalNearestID = from_door; + + for (map<int, AccessPoint*>::const_iterator itr1 = + _accessPoints.begin(); itr1 != _accessPoints.end(); ++itr1) { + + AccessPoint* to_AP = itr1->second; + + if(from_AP->GetID()==to_AP->GetID()) continue; + if(from_AP->GetFinalExitToOutside()) continue; + + //if(from_AP->GetFinalGoalOutside()) continue; + + if (to_AP->GetFinalExitToOutside()) { + + int to_door = _map_id_to_index[itr1->first]; + if (from_door == to_door) + continue; + + //cout <<" checking final destination: "<< pAccessPoints[j]->GetID()<<endl; + double dist = _distMatrix[from_door][to_door]; + if (dist < tmpMinDist) { + tmpFinalGlobalNearestID = to_door; + tmpMinDist = dist; + } + } + } + + // in the case it is the final APs + if (tmpFinalGlobalNearestID == from_door) + tmpMinDist = 0.0; + + if (tmpMinDist == FLT_MAX) { + Log->Write( + "ERROR: GlobalRouter: There is no visibility path from [%s] to the outside 1\n", + from_AP->GetFriendlyName().c_str()); + from_AP->Dump(); + exit(EXIT_FAILURE); + } + + // set the distance to the final destination ( OUT ) + from_AP->AddFinalDestination(FINAL_DEST_OUT, tmpMinDist); + + // set the intermediate path to global final destination + GetPath(from_door, tmpFinalGlobalNearestID); + + if (_tmpPedPath.size() >= 2) { + from_AP->AddTransitAPsTo(FINAL_DEST_OUT, _accessPoints[_map_index_to_id[_tmpPedPath[1]]]); - } else { - if ((!from_AP->GetFinalExitToOutside()) - && (!from_AP->IsClosed())) { - - Log->Write( - "ERROR: GlobalRouter: There is no visibility path from [%s] to the outside 2\n", - from_AP->GetFriendlyName().c_str()); - from_AP->Dump(); - exit(EXIT_FAILURE); - } - } - _tmpPedPath.clear(); - } - - - // set the configuration to reach the goals specified in the ini file - // set the distances to alternative destinations - - for (unsigned int p = 0; p < _finalDestinations.size(); p++) { - int to_door_uid = - _building->GetFinalGoal(_finalDestinations[p])->GetAllWalls()[0].GetUniqueID(); - int to_door_matrix_index=_map_id_to_index[to_door_uid]; - - // thats probably a goal located outside the geometry or not an exit from the geometry - if(to_door_uid==-1){ - Log->Write( - "ERROR: \tGlobalRouter: there is something wrong with final destination [ %d ]\n", - _finalDestinations[p]); - exit(EXIT_FAILURE); - } - - for (map<int, AccessPoint*>::const_iterator itr = - _accessPoints.begin(); itr != _accessPoints.end(); ++itr) { - - AccessPoint* from_AP = itr->second; - if(from_AP->GetFinalGoalOutside()) continue; - if(from_AP->IsClosed()) continue; - int from_door_matrix_index = _map_id_to_index[itr->first]; - - //comment this if you want infinite as distance to unreachable destinations - double dist = _distMatrix[from_door_matrix_index][to_door_matrix_index]; - from_AP->AddFinalDestination(_finalDestinations[p], dist); - - // set the intermediate path - // set the intermediate path to global final destination - GetPath(from_door_matrix_index, to_door_matrix_index); - if (_tmpPedPath.size() >= 2) { - from_AP->AddTransitAPsTo(_finalDestinations[p], - _accessPoints[_map_index_to_id[_tmpPedPath[1]]]); - } else { - if (((!from_AP->IsClosed()))) { - Log->Write( - "ERROR: GlobalRouter: There is no visibility path from [%s] to goal [%d]\n", - from_AP->GetFriendlyName().c_str(), _finalDestinations[p]); - from_AP->Dump(); - exit(EXIT_FAILURE); - } - } - _tmpPedPath.clear(); - } - } - - //dumping the complete system - //DumpAccessPoints(3-1); - //DumpAccessPoints(50); - //vector<string> rooms; - //rooms.push_back("hall"); - //rooms.push_back("0"); - //rooms.push_back("1"); - //rooms.push_back("2"); - //WriteGraphGV("routing_graph.gv",FINAL_DEST_OUT,rooms); - //WriteGraphGV("routing_graph.gv",1,rooms); - Log->Write("INFO:\tDone with the Global Router Engine!"); - //exit(0); + } else { + if ((!from_AP->GetFinalExitToOutside()) + && (!from_AP->IsClosed())) { + + Log->Write( + "ERROR: GlobalRouter: There is no visibility path from [%s] to the outside 2\n", + from_AP->GetFriendlyName().c_str()); + from_AP->Dump(); + exit(EXIT_FAILURE); + } + } + _tmpPedPath.clear(); + } + + + // set the configuration to reach the goals specified in the ini file + // set the distances to alternative destinations + + for (unsigned int p = 0; p < _finalDestinations.size(); p++) { + int to_door_uid = + _building->GetFinalGoal(_finalDestinations[p])->GetAllWalls()[0].GetUniqueID(); + int to_door_matrix_index=_map_id_to_index[to_door_uid]; + + // thats probably a goal located outside the geometry or not an exit from the geometry + if(to_door_uid==-1) { + Log->Write( + "ERROR: \tGlobalRouter: there is something wrong with final destination [ %d ]\n", + _finalDestinations[p]); + exit(EXIT_FAILURE); + } + + for (map<int, AccessPoint*>::const_iterator itr = + _accessPoints.begin(); itr != _accessPoints.end(); ++itr) { + + AccessPoint* from_AP = itr->second; + if(from_AP->GetFinalGoalOutside()) continue; + if(from_AP->IsClosed()) continue; + int from_door_matrix_index = _map_id_to_index[itr->first]; + + //comment this if you want infinite as distance to unreachable destinations + double dist = _distMatrix[from_door_matrix_index][to_door_matrix_index]; + from_AP->AddFinalDestination(_finalDestinations[p], dist); + + // set the intermediate path + // set the intermediate path to global final destination + GetPath(from_door_matrix_index, to_door_matrix_index); + if (_tmpPedPath.size() >= 2) { + from_AP->AddTransitAPsTo(_finalDestinations[p], + _accessPoints[_map_index_to_id[_tmpPedPath[1]]]); + } else { + if (((!from_AP->IsClosed()))) { + Log->Write( + "ERROR: GlobalRouter: There is no visibility path from [%s] to goal [%d]\n", + from_AP->GetFriendlyName().c_str(), _finalDestinations[p]); + from_AP->Dump(); + exit(EXIT_FAILURE); + } + } + _tmpPedPath.clear(); + } + } + + //dumping the complete system + //DumpAccessPoints(3-1); + //DumpAccessPoints(50); + //vector<string> rooms; + //rooms.push_back("hall"); + //rooms.push_back("0"); + //rooms.push_back("1"); + //rooms.push_back("2"); + //WriteGraphGV("routing_graph.gv",FINAL_DEST_OUT,rooms); + //WriteGraphGV("routing_graph.gv",1,rooms); + Log->Write("INFO:\tDone with the Global Router Engine!"); + //exit(0); } -void GlobalRouter::GetPath(int i, int j) { - if (_distMatrix[i][j] == FLT_MAX) - return; - if (i != j) - GetPath(i, _pathsMatrix[i][j]); - _tmpPedPath.push_back(j); +void GlobalRouter::GetPath(int i, int j) +{ + if (_distMatrix[i][j] == FLT_MAX) + return; + if (i != j) + GetPath(i, _pathsMatrix[i][j]); + _tmpPedPath.push_back(j); } -void GlobalRouter::GetPath(Pedestrian*ped, int goalID, std::vector<SubRoom*>& path){ - - //clear the global variable holding the paths - _tmpPedPath.clear(); - - int tmpFinalDest=ped->GetFinalDestination(); - ped->SetFinalDestination(goalID); - - //find the nearest APs and start from there - int next = GetBestDefaultRandomExit(ped); - if(next==-1){ - Log->Write("ERROR:\t there is an error in getting the path for ped %d to the goal %d", ped->GetID(),goalID); - exit(EXIT_FAILURE); - } - - // get the transformed goal_id - int to_door_uid = - _building->GetFinalGoal(goalID)->GetAllWalls()[0].GetUniqueID(); - int to_door_matrix_index=_map_id_to_index[to_door_uid]; - int from_door_matrix_index=_map_id_to_index[next]; - - // thats probably a goal located outside the geometry or not an exit from the geometry - if(to_door_uid==-1){ - Log->Write("ERROR: \tGlobalRouter: there is something wrong with final destination [ %d ]\n",goalID); - exit(EXIT_FAILURE); - } - - //populate the line unique id to cross - GetPath(from_door_matrix_index,to_door_matrix_index); - - for(unsigned int i=0;i<_tmpPedPath.size();i++){ - int ap_id= _map_index_to_id[_tmpPedPath[i]]; - int subroom_uid=_accessPoints[ap_id]->GetConnectingRoom1(); - if(subroom_uid==-1) continue; - SubRoom* sub = _building->GetSubRoomByUID(subroom_uid); - if (sub && IsElementInVector(path, sub)==false) path.push_back(sub); - } - - for(unsigned int i=0;i<_tmpPedPath.size();i++){ - int ap_id= _map_index_to_id[_tmpPedPath[i]]; - int subroom_uid=_accessPoints[ap_id]->GetConnectingRoom2(); - if(subroom_uid==-1) continue; - SubRoom* sub = _building->GetSubRoomByUID(subroom_uid); - if (sub && IsElementInVector(path, sub)==false) path.push_back(sub); - } - - //clear the global variable holding the paths - _tmpPedPath.clear(); - - ped->SetFinalDestination(tmpFinalDest); - //double distance = _accessPoints[next]->GetDistanceTo(0)+ped->GetDistanceToNextTarget(); - //cout<<"shortest distance to outside: " <<distance<<endl; +void GlobalRouter::GetPath(Pedestrian*ped, int goalID, std::vector<SubRoom*>& path) +{ + + //clear the global variable holding the paths + _tmpPedPath.clear(); + + int tmpFinalDest=ped->GetFinalDestination(); + ped->SetFinalDestination(goalID); + + //find the nearest APs and start from there + int next = GetBestDefaultRandomExit(ped); + if(next==-1) { + Log->Write("ERROR:\t there is an error in getting the path for ped %d to the goal %d", ped->GetID(),goalID); + exit(EXIT_FAILURE); + } + + // get the transformed goal_id + int to_door_uid = + _building->GetFinalGoal(goalID)->GetAllWalls()[0].GetUniqueID(); + int to_door_matrix_index=_map_id_to_index[to_door_uid]; + int from_door_matrix_index=_map_id_to_index[next]; + + // thats probably a goal located outside the geometry or not an exit from the geometry + if(to_door_uid==-1) { + Log->Write("ERROR: \tGlobalRouter: there is something wrong with final destination [ %d ]\n",goalID); + exit(EXIT_FAILURE); + } + + //populate the line unique id to cross + GetPath(from_door_matrix_index,to_door_matrix_index); + + for(unsigned int i=0; i<_tmpPedPath.size(); i++) { + int ap_id= _map_index_to_id[_tmpPedPath[i]]; + int subroom_uid=_accessPoints[ap_id]->GetConnectingRoom1(); + if(subroom_uid==-1) continue; + SubRoom* sub = _building->GetSubRoomByUID(subroom_uid); + if (sub && IsElementInVector(path, sub)==false) path.push_back(sub); + } + + for(unsigned int i=0; i<_tmpPedPath.size(); i++) { + int ap_id= _map_index_to_id[_tmpPedPath[i]]; + int subroom_uid=_accessPoints[ap_id]->GetConnectingRoom2(); + if(subroom_uid==-1) continue; + SubRoom* sub = _building->GetSubRoomByUID(subroom_uid); + if (sub && IsElementInVector(path, sub)==false) path.push_back(sub); + } + + //clear the global variable holding the paths + _tmpPedPath.clear(); + + ped->SetFinalDestination(tmpFinalDest); + //double distance = _accessPoints[next]->GetDistanceTo(0)+ped->GetDistanceToNextTarget(); + //cout<<"shortest distance to outside: " <<distance<<endl; } @@ -537,525 +542,529 @@ void GlobalRouter::GetPath(Pedestrian*ped, int goalID, std::vector<SubRoom*>& pa between i and j if it exists (i.e. if there's a path between i and j) or 0, otherwise */ -void GlobalRouter::FloydWarshall() { - const int n = _building->GetNumberOfGoals() + _building->GetAllGoals().size(); - for (int k = 0; k < n; k++) - for (int i = 0; i < n; i++) - for (int j = 0; j < n; j++) - if (_distMatrix[i][k] + _distMatrix[k][j] < _distMatrix[i][j]) { - _distMatrix[i][j] = _distMatrix[i][k] + _distMatrix[k][j]; - _pathsMatrix[i][j] = _pathsMatrix[k][j]; - } +void GlobalRouter::FloydWarshall() +{ + const int n = _building->GetNumberOfGoals() + _building->GetAllGoals().size(); + for (int k = 0; k < n; k++) + for (int i = 0; i < n; i++) + for (int j = 0; j < n; j++) + if (_distMatrix[i][k] + _distMatrix[k][j] < _distMatrix[i][j]) { + _distMatrix[i][j] = _distMatrix[i][k] + _distMatrix[k][j]; + _pathsMatrix[i][j] = _pathsMatrix[k][j]; + } } -void GlobalRouter::DumpAccessPoints(int p) { - if (p != -1) { - _accessPoints.at(p)->Dump(); - } else { - for (map<int, AccessPoint*>::const_iterator itr = _accessPoints.begin(); - itr != _accessPoints.end(); ++itr) { - itr->second->Dump(); - } - } +void GlobalRouter::DumpAccessPoints(int p) +{ + if (p != -1) { + _accessPoints.at(p)->Dump(); + } else { + for (map<int, AccessPoint*>::const_iterator itr = _accessPoints.begin(); + itr != _accessPoints.end(); ++itr) { + itr->second->Dump(); + } + } } -int GlobalRouter::FindExit(Pedestrian* ped) { +int GlobalRouter::FindExit(Pedestrian* ped) +{ - int nextDestination = ped->GetNextDestination(); + int nextDestination = ped->GetNextDestination(); // if(ped->GetGlobalTime()>80){ // ped->Dump(2); // //exit(0); // } - if (nextDestination == -1) { - return GetBestDefaultRandomExit(ped); - - } else { - - SubRoom* sub = _building->GetRoom(ped->GetRoomID())->GetSubRoom( - ped->GetSubRoomID()); - - const vector<int>& accessPointsInSubRoom = sub->GetAllGoalIDs(); - for (unsigned int i = 0; i < accessPointsInSubRoom.size(); i++) { - - int apID = accessPointsInSubRoom[i]; - AccessPoint* ap = _accessPoints[apID]; - - const Point& pt3 = ped->GetPos(); - double distToExit = ap->GetNavLine()->DistTo(pt3); - - if (distToExit > J_EPS_DIST) - continue; - - //one AP is near actualize destination: - nextDestination = ap->GetNearestTransitAPTO( - ped->GetFinalDestination()); - - - if (nextDestination == -1) { // we are almost at the exit - return ped->GetNextDestination(); - } else { - //check that the next destination is in the actual room of the pedestrian - if (_accessPoints[nextDestination]->isInRange( - sub->GetUID())==false) { - //return the last destination if defined - int previousDestination = ped->GetNextDestination(); - - //we are still somewhere in the initialization phase - if (previousDestination == -1) { - ped->SetExitIndex(apID); - ped->SetExitLine(_accessPoints[apID]->GetNavLine()); - return apID; - } else // we are still having a valid destination, don't change - { - return previousDestination; - } - } else // we have reached the new room - { - ped->SetExitIndex(nextDestination); - ped->SetExitLine( - _accessPoints[nextDestination]->GetNavLine()); - return nextDestination; - } - } - } - - // still have a valid destination, so return it - return nextDestination; - } + if (nextDestination == -1) { + return GetBestDefaultRandomExit(ped); + + } else { + + SubRoom* sub = _building->GetRoom(ped->GetRoomID())->GetSubRoom( + ped->GetSubRoomID()); + + const vector<int>& accessPointsInSubRoom = sub->GetAllGoalIDs(); + for (unsigned int i = 0; i < accessPointsInSubRoom.size(); i++) { + + int apID = accessPointsInSubRoom[i]; + AccessPoint* ap = _accessPoints[apID]; + + const Point& pt3 = ped->GetPos(); + double distToExit = ap->GetNavLine()->DistTo(pt3); + + if (distToExit > J_EPS_DIST) + continue; + + //one AP is near actualize destination: + nextDestination = ap->GetNearestTransitAPTO( + ped->GetFinalDestination()); + + + if (nextDestination == -1) { // we are almost at the exit + return ped->GetNextDestination(); + } else { + //check that the next destination is in the actual room of the pedestrian + if (_accessPoints[nextDestination]->isInRange( + sub->GetUID())==false) { + //return the last destination if defined + int previousDestination = ped->GetNextDestination(); + + //we are still somewhere in the initialization phase + if (previousDestination == -1) { + ped->SetExitIndex(apID); + ped->SetExitLine(_accessPoints[apID]->GetNavLine()); + return apID; + } else { // we are still having a valid destination, don't change + return previousDestination; + } + } else { // we have reached the new room + ped->SetExitIndex(nextDestination); + ped->SetExitLine( + _accessPoints[nextDestination]->GetNavLine()); + return nextDestination; + } + } + } + + // still have a valid destination, so return it + return nextDestination; + } } -int GlobalRouter::GetBestDefaultRandomExit(Pedestrian* ped) { - // get the opened exits - SubRoom* sub = _building->GetRoom(ped->GetRoomID())->GetSubRoom( - ped->GetSubRoomID()); - - - - // get the relevant opened exits - vector <AccessPoint*> relevantAPs; - GetRelevantRoutesTofinalDestination(ped,relevantAPs); - //cout<<"relevant APs size:" <<relevantAPs.size()<<endl; - - int bestAPsID = -1; - double minDist = FLT_MAX; - - //for (unsigned int i = 0; i < accessPointsInSubRoom.size(); i++) { - // int apID = accessPointsInSubRoom[i]; - for(unsigned int g=0;g<relevantAPs.size();g++){ - AccessPoint* ap=relevantAPs[g]; - //int exitid=ap->GetID(); - - //AccessPoint* ap = _accessPoints[apID]; - - if (ap->isInRange(sub->GetUID()) == false) - continue; - //check if that exit is open. - if (ap->IsClosed()) - continue; - - //the line from the current position to the centre of the nav line. - // at least the line in that direction minus EPS - const Point& posA = ped->GetPos(); - const Point& posB = ap->GetNavLine()->GetCentre(); - const Point& posC = (posB - posA).Normalized() - * ((posA - posB).Norm() - J_EPS) + posA; - - - //check if visible - if (sub->IsVisible(posA, posC, true) == false){ - ped->RerouteIn(10); - //ped->Dump(ped->GetID()); - continue; - } - - double dist = ap->GetDistanceTo(ped->GetFinalDestination()) - + ap->DistanceTo(posA.GetX(), posA.GetY()); - - - if (dist < minDist) { - bestAPsID = ap->GetID(); - minDist = dist; - } - } - - if (bestAPsID != -1) { - ped->SetExitIndex(bestAPsID); - ped->SetExitLine(_accessPoints[bestAPsID]->GetNavLine()); - return bestAPsID; - } else { - if (_building->GetRoom(ped->GetRoomID())->GetCaption() != "outside") - Log->Write( - "ERROR:\t Cannot find valid destination for ped [%d] located in room [%d] subroom [%d] going to destination [%d]", - ped->GetID(), ped->GetRoomID(), ped->GetSubRoomID(), - ped->GetFinalDestination()); - //exit(EXIT_FAILURE); - return -1; - } +int GlobalRouter::GetBestDefaultRandomExit(Pedestrian* ped) +{ + // get the opened exits + SubRoom* sub = _building->GetRoom(ped->GetRoomID())->GetSubRoom( + ped->GetSubRoomID()); + + + + // get the relevant opened exits + vector <AccessPoint*> relevantAPs; + GetRelevantRoutesTofinalDestination(ped,relevantAPs); + //cout<<"relevant APs size:" <<relevantAPs.size()<<endl; + + int bestAPsID = -1; + double minDist = FLT_MAX; + + //for (unsigned int i = 0; i < accessPointsInSubRoom.size(); i++) { + // int apID = accessPointsInSubRoom[i]; + for(unsigned int g=0; g<relevantAPs.size(); g++) { + AccessPoint* ap=relevantAPs[g]; + //int exitid=ap->GetID(); + + //AccessPoint* ap = _accessPoints[apID]; + + if (ap->isInRange(sub->GetUID()) == false) + continue; + //check if that exit is open. + if (ap->IsClosed()) + continue; + + //the line from the current position to the centre of the nav line. + // at least the line in that direction minus EPS + const Point& posA = ped->GetPos(); + const Point& posB = ap->GetNavLine()->GetCentre(); + const Point& posC = (posB - posA).Normalized() + * ((posA - posB).Norm() - J_EPS) + posA; + + + //check if visible + if (sub->IsVisible(posA, posC, true) == false) { + ped->RerouteIn(10); + //ped->Dump(ped->GetID()); + continue; + } + + double dist = ap->GetDistanceTo(ped->GetFinalDestination()) + + ap->DistanceTo(posA.GetX(), posA.GetY()); + + + if (dist < minDist) { + bestAPsID = ap->GetID(); + minDist = dist; + } + } + + if (bestAPsID != -1) { + ped->SetExitIndex(bestAPsID); + ped->SetExitLine(_accessPoints[bestAPsID]->GetNavLine()); + return bestAPsID; + } else { + if (_building->GetRoom(ped->GetRoomID())->GetCaption() != "outside") + Log->Write( + "ERROR:\t Cannot find valid destination for ped [%d] located in room [%d] subroom [%d] going to destination [%d]", + ped->GetID(), ped->GetRoomID(), ped->GetSubRoomID(), + ped->GetFinalDestination()); + //exit(EXIT_FAILURE); + return -1; + } } -void GlobalRouter::GetRelevantRoutesTofinalDestination(Pedestrian *ped, vector<AccessPoint*>& relevantAPS){ - - //collect all the aps in the room - vector<AccessPoint*>toBeDeleted; - - Room* room=_building->GetRoom(ped->GetRoomID()); - SubRoom* sub=room->GetSubRoom(ped->GetSubRoomID()); - - //first check with all goals ids. The hlines should normally be filtered out - // if any problems then try taking only transitions - //const vector<int>& goals=room->GetAllTransitionsIDs(); - const vector<int>& goals=sub->GetAllGoalIDs(); - //filter to keep only the emergencies exits. - - for(unsigned int g1=0;g1<goals.size();g1++){ - AccessPoint* ap=_accessPoints[goals[g1]]; - bool relevant=true; - for(unsigned int g2=0;g2<goals.size();g2++){ - if(goals[g2]==goals[g1]) continue; // always skeep myself - if(ap->GetNearestTransitAPTO(ped->GetFinalDestination())==goals[g2]){ - //FIXME there are interference with hlines. suitable only for quickest route considering exits, - // crossings only - relevant=false; - break; - } - } - if(relevant==true){ - relevantAPS.push_back(ap); - //cout<<"relevant APs:" <<ap->GetID()<<endl; - } - } - - // remove all the aps which points to one in the same room - //return the remaining. They represent unique routes to the final destination +void GlobalRouter::GetRelevantRoutesTofinalDestination(Pedestrian *ped, vector<AccessPoint*>& relevantAPS) +{ + + //collect all the aps in the room + vector<AccessPoint*>toBeDeleted; + + Room* room=_building->GetRoom(ped->GetRoomID()); + SubRoom* sub=room->GetSubRoom(ped->GetSubRoomID()); + + //first check with all goals ids. The hlines should normally be filtered out + // if any problems then try taking only transitions + //const vector<int>& goals=room->GetAllTransitionsIDs(); + const vector<int>& goals=sub->GetAllGoalIDs(); + //filter to keep only the emergencies exits. + + for(unsigned int g1=0; g1<goals.size(); g1++) { + AccessPoint* ap=_accessPoints[goals[g1]]; + bool relevant=true; + for(unsigned int g2=0; g2<goals.size(); g2++) { + if(goals[g2]==goals[g1]) continue; // always skeep myself + if(ap->GetNearestTransitAPTO(ped->GetFinalDestination())==goals[g2]) { + //FIXME there are interference with hlines. suitable only for quickest route considering exits, + // crossings only + relevant=false; + break; + } + } + if(relevant==true) { + relevantAPS.push_back(ap); + //cout<<"relevant APs:" <<ap->GetID()<<endl; + } + } + + // remove all the aps which points to one in the same room + //return the remaining. They represent unique routes to the final destination } -SubRoom* GlobalRouter::GetCommonSubRoom(Crossing* c1, Crossing* c2) { - SubRoom* sb11 = c1->GetSubRoom1(); - SubRoom* sb12 = c1->GetSubRoom2(); - SubRoom* sb21 = c2->GetSubRoom1(); - SubRoom* sb22 = c2->GetSubRoom2(); - - if (sb11 == sb21) - return sb11; - if (sb11 == sb22) - return sb11; - if (sb12 == sb21) - return sb12; - if (sb12 == sb22) - return sb12; - - return NULL; +SubRoom* GlobalRouter::GetCommonSubRoom(Crossing* c1, Crossing* c2) +{ + SubRoom* sb11 = c1->GetSubRoom1(); + SubRoom* sb12 = c1->GetSubRoom2(); + SubRoom* sb21 = c2->GetSubRoom1(); + SubRoom* sb22 = c2->GetSubRoom2(); + + if (sb11 == sb21) + return sb11; + if (sb11 == sb22) + return sb11; + if (sb12 == sb21) + return sb12; + if (sb12 == sb22) + return sb12; + + return NULL; } void GlobalRouter::WriteGraphGV(string filename, int finalDestination, - const vector<string> rooms_captions) { - ofstream graph_file(filename.c_str()); - if (graph_file.is_open() == false) { - Log->Write("Unable to open file" + filename); - return; - } - - //header - graph_file << "## Produced by OPS_GCFM" << endl; - //graph_file << "##comand: \" sfdp -Goverlap=prism -Gcharset=latin1"<<filename <<"| gvmap -e | neato -Ecolor=\"#55555522\" -n2 -Tpng > "<< filename<<".png \""<<endl; - graph_file << "##Command to produce the output: \"neato -n -s -Tpng " - << filename << " > " << filename << ".png\"" << endl; - graph_file << "digraph OPS_GCFM_ROUTING {" << endl; - graph_file << "overlap=scale;" << endl; - graph_file << "splines=false;" << endl; - graph_file << "fontsize=20;" << endl; - graph_file - << "label=\"Graph generated by the routing engine for destination: " - << finalDestination << "\"" << endl; - - vector<int> rooms_ids = vector<int>(); - - if (rooms_captions.empty()) { - // then all rooms should be printed - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - rooms_ids.push_back(i); - } - - } else { - for (unsigned int i = 0; i < rooms_captions.size(); i++) { - rooms_ids.push_back( - _building->GetRoom(rooms_captions[i])->GetID()); - } - } - - for (map<int, AccessPoint*>::const_iterator itr = _accessPoints.begin(); - itr != _accessPoints.end(); ++itr) { - - AccessPoint* from_AP = itr->second; - - int from_door = from_AP->GetID(); - - // check for valid room - NavLine* nav = from_AP->GetNavLine(); - int room_id = -1; - - if (dynamic_cast<Crossing*>(nav) != NULL) { - room_id = ((Crossing*) (nav))->GetRoom1()->GetID(); - - } else if (dynamic_cast<Hline*>(nav) != NULL) { - room_id = ((Hline*) (nav))->GetRoom()->GetID(); - - } else if (dynamic_cast<Transition*>(nav) != NULL) { - room_id = ((Transition*) (nav))->GetRoom1()->GetID(); - - } else { - cout << "WARNING: Unkown navigation line type" << endl; - continue; - } - - if (IsElementInVector(rooms_ids, room_id) == false) - continue; - - double px = from_AP->GetCentre().GetX(); - double py = from_AP->GetCentre().GetY(); - //graph_file << from_door <<" [shape=ellipse, pos=\""<<px<<", "<<py<<" \"] ;"<<endl; - //graph_file << from_door <<" [shape=ellipse, pos=\""<<px<<","<<py<<"\" ];"<<endl; - - //const vector<AccessPoint*>& from_aps = from_AP->GetConnectingAPs(); - const vector<AccessPoint*>& from_aps = from_AP->GetTransitAPsTo( - finalDestination); - - if (from_aps.size() == 0) { - - if (from_AP->GetFinalExitToOutside()) { - graph_file << from_door << " [pos=\"" << px << ", " << py - << " \", style=filled, color=green,fontsize=5] ;" - << endl; - // graph_file << from_door <<" [width=\"0.41\", height=\"0.31\",fixedsize=false,pos=\""<<px<<", "<<py<<" \", style=filled, color=green,fontsize=4] ;"<<endl; - } else { - graph_file << from_door << " [pos=\"" << px << ", " << py - << " \", style=filled, color=red,fontsize=5] ;" << endl; - // graph_file << from_door <<" [width=\"0.41\", height=\"0.31\",fixedsize=false,pos=\""<<px<<", "<<py<<" \", style=filled, color=red,fontsize=4] ;"<<endl; - } - } else { - // check that all connecting aps are contained in the room_ids list - // if not marked as sink. - bool isSink = true; - for (unsigned int j = 0; j < from_aps.size(); j++) { - NavLine* nav = from_aps[j]->GetNavLine(); - int room_id = -1; - - if (dynamic_cast<Crossing*>(nav) != NULL) { - room_id = ((Crossing*) (nav))->GetRoom1()->GetID(); - - } else if (dynamic_cast<Hline*>(nav) != NULL) { - room_id = ((Hline*) (nav))->GetRoom()->GetID(); - - } else if (dynamic_cast<Transition*>(nav) != NULL) { - room_id = ((Transition*) (nav))->GetRoom1()->GetID(); - - } else { - cout << "WARNING: Unkown navigation line type" << endl; - continue; - } - - if (IsElementInVector(rooms_ids, room_id) == true) { - isSink = false; - break; - } - } - - if (isSink) { - //graph_file << from_door <<" [width=\"0.3\", height=\"0.21\",fixedsize=false,pos=\""<<px<<", "<<py<<" \" ,style=filled, color=green, fontsize=4] ;"<<endl; - graph_file << from_door << " [pos=\"" << px << ", " << py - << " \" ,style=filled, color=blue, fontsize=5] ;" - << endl; - } else { - //graph_file << from_door <<" [width=\"0.3\", height=\"0.231\",fixedsize=false, pos=\""<<px<<", "<<py<<" \", fontsize=4] ;"<<endl; - graph_file << from_door << " [pos=\"" << px << ", " << py - << " \", style=filled, color=yellow, fontsize=5] ;" - << endl; - } - } - - } - - //connections - for (map<int, AccessPoint*>::const_iterator itr = _accessPoints.begin(); - itr != _accessPoints.end(); ++itr) { - - AccessPoint* from_AP = itr->second; - int from_door = from_AP->GetID(); + const vector<string> rooms_captions) +{ + ofstream graph_file(filename.c_str()); + if (graph_file.is_open() == false) { + Log->Write("Unable to open file" + filename); + return; + } + + //header + graph_file << "## Produced by OPS_GCFM" << endl; + //graph_file << "##comand: \" sfdp -Goverlap=prism -Gcharset=latin1"<<filename <<"| gvmap -e | neato -Ecolor=\"#55555522\" -n2 -Tpng > "<< filename<<".png \""<<endl; + graph_file << "##Command to produce the output: \"neato -n -s -Tpng " + << filename << " > " << filename << ".png\"" << endl; + graph_file << "digraph OPS_GCFM_ROUTING {" << endl; + graph_file << "overlap=scale;" << endl; + graph_file << "splines=false;" << endl; + graph_file << "fontsize=20;" << endl; + graph_file + << "label=\"Graph generated by the routing engine for destination: " + << finalDestination << "\"" << endl; + + vector<int> rooms_ids = vector<int>(); + + if (rooms_captions.empty()) { + // then all rooms should be printed + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + rooms_ids.push_back(i); + } + + } else { + for (unsigned int i = 0; i < rooms_captions.size(); i++) { + rooms_ids.push_back( + _building->GetRoom(rooms_captions[i])->GetID()); + } + } + + for (map<int, AccessPoint*>::const_iterator itr = _accessPoints.begin(); + itr != _accessPoints.end(); ++itr) { + + AccessPoint* from_AP = itr->second; + + int from_door = from_AP->GetID(); + + // check for valid room + NavLine* nav = from_AP->GetNavLine(); + int room_id = -1; + + if (dynamic_cast<Crossing*>(nav) != NULL) { + room_id = ((Crossing*) (nav))->GetRoom1()->GetID(); + + } else if (dynamic_cast<Hline*>(nav) != NULL) { + room_id = ((Hline*) (nav))->GetRoom()->GetID(); + + } else if (dynamic_cast<Transition*>(nav) != NULL) { + room_id = ((Transition*) (nav))->GetRoom1()->GetID(); + + } else { + cout << "WARNING: Unkown navigation line type" << endl; + continue; + } + + if (IsElementInVector(rooms_ids, room_id) == false) + continue; + + double px = from_AP->GetCentre().GetX(); + double py = from_AP->GetCentre().GetY(); + //graph_file << from_door <<" [shape=ellipse, pos=\""<<px<<", "<<py<<" \"] ;"<<endl; + //graph_file << from_door <<" [shape=ellipse, pos=\""<<px<<","<<py<<"\" ];"<<endl; + + //const vector<AccessPoint*>& from_aps = from_AP->GetConnectingAPs(); + const vector<AccessPoint*>& from_aps = from_AP->GetTransitAPsTo( + finalDestination); + + if (from_aps.size() == 0) { + + if (from_AP->GetFinalExitToOutside()) { + graph_file << from_door << " [pos=\"" << px << ", " << py + << " \", style=filled, color=green,fontsize=5] ;" + << endl; + // graph_file << from_door <<" [width=\"0.41\", height=\"0.31\",fixedsize=false,pos=\""<<px<<", "<<py<<" \", style=filled, color=green,fontsize=4] ;"<<endl; + } else { + graph_file << from_door << " [pos=\"" << px << ", " << py + << " \", style=filled, color=red,fontsize=5] ;" << endl; + // graph_file << from_door <<" [width=\"0.41\", height=\"0.31\",fixedsize=false,pos=\""<<px<<", "<<py<<" \", style=filled, color=red,fontsize=4] ;"<<endl; + } + } else { + // check that all connecting aps are contained in the room_ids list + // if not marked as sink. + bool isSink = true; + for (unsigned int j = 0; j < from_aps.size(); j++) { + NavLine* nav = from_aps[j]->GetNavLine(); + int room_id = -1; + + if (dynamic_cast<Crossing*>(nav) != NULL) { + room_id = ((Crossing*) (nav))->GetRoom1()->GetID(); + + } else if (dynamic_cast<Hline*>(nav) != NULL) { + room_id = ((Hline*) (nav))->GetRoom()->GetID(); + + } else if (dynamic_cast<Transition*>(nav) != NULL) { + room_id = ((Transition*) (nav))->GetRoom1()->GetID(); + + } else { + cout << "WARNING: Unkown navigation line type" << endl; + continue; + } + + if (IsElementInVector(rooms_ids, room_id) == true) { + isSink = false; + break; + } + } + + if (isSink) { + //graph_file << from_door <<" [width=\"0.3\", height=\"0.21\",fixedsize=false,pos=\""<<px<<", "<<py<<" \" ,style=filled, color=green, fontsize=4] ;"<<endl; + graph_file << from_door << " [pos=\"" << px << ", " << py + << " \" ,style=filled, color=blue, fontsize=5] ;" + << endl; + } else { + //graph_file << from_door <<" [width=\"0.3\", height=\"0.231\",fixedsize=false, pos=\""<<px<<", "<<py<<" \", fontsize=4] ;"<<endl; + graph_file << from_door << " [pos=\"" << px << ", " << py + << " \", style=filled, color=yellow, fontsize=5] ;" + << endl; + } + } + + } + + //connections + for (map<int, AccessPoint*>::const_iterator itr = _accessPoints.begin(); + itr != _accessPoints.end(); ++itr) { + + AccessPoint* from_AP = itr->second; + int from_door = from_AP->GetID(); - //const vector<AccessPoint*>& aps = from_AP->GetConnectingAPs(); - const vector<AccessPoint*>& aps = from_AP->GetTransitAPsTo( - finalDestination); + //const vector<AccessPoint*>& aps = from_AP->GetConnectingAPs(); + const vector<AccessPoint*>& aps = from_AP->GetTransitAPsTo( + finalDestination); - NavLine* nav = from_AP->GetNavLine(); - int room_id = -1; - - if (dynamic_cast<Crossing*>(nav) != NULL) { - room_id = ((Crossing*) (nav))->GetRoom1()->GetID(); - - } else if (dynamic_cast<Hline*>(nav) != NULL) { - room_id = ((Hline*) (nav))->GetRoom()->GetID(); - - } else if (dynamic_cast<Transition*>(nav) != NULL) { - room_id = ((Transition*) (nav))->GetRoom1()->GetID(); - - } else { - cout << "WARNING: Unkown navigation line type" << endl; - continue; - } - - if (IsElementInVector(rooms_ids, room_id) == false) - continue; - - for (unsigned int j = 0; j < aps.size(); j++) { - AccessPoint* to_AP = aps[j]; - int to_door = to_AP->GetID(); - - NavLine* nav = to_AP->GetNavLine(); - int room_id = -1; - - if (dynamic_cast<Crossing*>(nav) != NULL) { - room_id = ((Crossing*) (nav))->GetRoom1()->GetID(); - - } else if (dynamic_cast<Hline*>(nav) != NULL) { - room_id = ((Hline*) (nav))->GetRoom()->GetID(); - - } else if (dynamic_cast<Transition*>(nav) != NULL) { - room_id = ((Transition*) (nav))->GetRoom1()->GetID(); - - } else { - cout << "WARNING: Unkown navigation line type" << endl; - continue; - } - - if (IsElementInVector(rooms_ids, room_id) == false) - continue; - - graph_file << from_door << " -> " << to_door << " [ label=" - << from_AP->GetDistanceTo(to_AP) - + to_AP->GetDistanceTo(finalDestination) - << ", fontsize=10]; " << endl; - } - } + NavLine* nav = from_AP->GetNavLine(); + int room_id = -1; + + if (dynamic_cast<Crossing*>(nav) != NULL) { + room_id = ((Crossing*) (nav))->GetRoom1()->GetID(); + + } else if (dynamic_cast<Hline*>(nav) != NULL) { + room_id = ((Hline*) (nav))->GetRoom()->GetID(); + + } else if (dynamic_cast<Transition*>(nav) != NULL) { + room_id = ((Transition*) (nav))->GetRoom1()->GetID(); + + } else { + cout << "WARNING: Unkown navigation line type" << endl; + continue; + } + + if (IsElementInVector(rooms_ids, room_id) == false) + continue; + + for (unsigned int j = 0; j < aps.size(); j++) { + AccessPoint* to_AP = aps[j]; + int to_door = to_AP->GetID(); + + NavLine* nav = to_AP->GetNavLine(); + int room_id = -1; + + if (dynamic_cast<Crossing*>(nav) != NULL) { + room_id = ((Crossing*) (nav))->GetRoom1()->GetID(); + + } else if (dynamic_cast<Hline*>(nav) != NULL) { + room_id = ((Hline*) (nav))->GetRoom()->GetID(); + + } else if (dynamic_cast<Transition*>(nav) != NULL) { + room_id = ((Transition*) (nav))->GetRoom1()->GetID(); + + } else { + cout << "WARNING: Unkown navigation line type" << endl; + continue; + } + + if (IsElementInVector(rooms_ids, room_id) == false) + continue; + + graph_file << from_door << " -> " << to_door << " [ label=" + << from_AP->GetDistanceTo(to_AP) + + to_AP->GetDistanceTo(finalDestination) + << ", fontsize=10]; " << endl; + } + } - //graph_file << "node [shape=box]; gy2; yr2; rg2; gy1; yr1; rg1;"<<endl; - //graph_file << "node [shape=circle,fixedsize=true,width=0.9]; green2; yellow2; red2; safe2; safe1; green1; yellow1; red1;"<<endl; + //graph_file << "node [shape=box]; gy2; yr2; rg2; gy1; yr1; rg1;"<<endl; + //graph_file << "node [shape=circle,fixedsize=true,width=0.9]; green2; yellow2; red2; safe2; safe1; green1; yellow1; red1;"<<endl; - //graph_file << "0 -> 1 ;"<<endl; + //graph_file << "0 -> 1 ;"<<endl; - graph_file << "}" << endl; + graph_file << "}" << endl; - //done - graph_file.close(); + //done + graph_file.close(); } -string GlobalRouter::GetRoutingInfoFile() const { - - TiXmlDocument doc(_building->GetProjectFilename()); - if (!doc.LoadFile()){ - Log->Write("ERROR: \t%s", doc.ErrorDesc()); - Log->Write("ERROR: \t could not parse the project file"); - exit(EXIT_FAILURE); - } - - // everything is fine. proceed with parsing - TiXmlElement* xMainNode = doc.RootElement(); - TiXmlNode* xRouters=xMainNode->FirstChild("route_choice_models"); - - string nav_line_file=""; - - for(TiXmlElement* e = xRouters->FirstChildElement("router"); e; - e = e->NextSiblingElement("router")) { - - string strategy=e->Attribute("description"); - - if(strategy=="local_shortest") { - if (e->FirstChild("parameters")->FirstChildElement("navigation_lines")) - nav_line_file=e->FirstChild("parameters")->FirstChildElement("navigation_lines")->Attribute("file"); - } - else if(strategy=="global_shortest") { - if (e->FirstChild("parameters")->FirstChildElement("navigation_lines")) - nav_line_file=e->FirstChild("parameters")->FirstChildElement("navigation_lines")->Attribute("file"); - } - else if(strategy=="global_safest") { - if (e->FirstChild("parameters")->FirstChildElement("navigation_lines")) - nav_line_file=e->FirstChild("parameters")->FirstChildElement("navigation_lines")->Attribute("file"); - } - else if(strategy=="dynamic") { - if (e->FirstChild("parameters")->FirstChildElement("navigation_lines")) - nav_line_file=e->FirstChild("parameters")->FirstChildElement("navigation_lines")->Attribute("file"); - } - } - if (nav_line_file == "") - return nav_line_file; - else - return _building->GetProjectRootDir()+nav_line_file; +string GlobalRouter::GetRoutingInfoFile() const +{ + + TiXmlDocument doc(_building->GetProjectFilename()); + if (!doc.LoadFile()) { + Log->Write("ERROR: \t%s", doc.ErrorDesc()); + Log->Write("ERROR: \t could not parse the project file"); + exit(EXIT_FAILURE); + } + + // everything is fine. proceed with parsing + TiXmlElement* xMainNode = doc.RootElement(); + TiXmlNode* xRouters=xMainNode->FirstChild("route_choice_models"); + + string nav_line_file=""; + + for(TiXmlElement* e = xRouters->FirstChildElement("router"); e; + e = e->NextSiblingElement("router")) { + + string strategy=e->Attribute("description"); + + if(strategy=="local_shortest") { + if (e->FirstChild("parameters")->FirstChildElement("navigation_lines")) + nav_line_file=e->FirstChild("parameters")->FirstChildElement("navigation_lines")->Attribute("file"); + } else if(strategy=="global_shortest") { + if (e->FirstChild("parameters")->FirstChildElement("navigation_lines")) + nav_line_file=e->FirstChild("parameters")->FirstChildElement("navigation_lines")->Attribute("file"); + } else if(strategy=="global_safest") { + if (e->FirstChild("parameters")->FirstChildElement("navigation_lines")) + nav_line_file=e->FirstChild("parameters")->FirstChildElement("navigation_lines")->Attribute("file"); + } else if(strategy=="dynamic") { + if (e->FirstChild("parameters")->FirstChildElement("navigation_lines")) + nav_line_file=e->FirstChild("parameters")->FirstChildElement("navigation_lines")->Attribute("file"); + } + } + if (nav_line_file == "") + return nav_line_file; + else + return _building->GetProjectRootDir()+nav_line_file; } -void GlobalRouter::LoadRoutingInfos(const std::string &filename){ +void GlobalRouter::LoadRoutingInfos(const std::string &filename) +{ - if(filename=="") return; + if(filename=="") return; - Log->Write("INFO:\tLoading extra routing information for the global/quickest path router"); - Log->Write("INFO:\t from the file "+filename); + Log->Write("INFO:\tLoading extra routing information for the global/quickest path router"); + Log->Write("INFO:\t from the file "+filename); - TiXmlDocument docRouting(filename); - if (!docRouting.LoadFile()){ - Log->Write("ERROR: \t%s", docRouting.ErrorDesc()); - Log->Write("ERROR: \t could not parse the routing file [%s]",filename.c_str()); - exit(EXIT_FAILURE); - } + TiXmlDocument docRouting(filename); + if (!docRouting.LoadFile()) { + Log->Write("ERROR: \t%s", docRouting.ErrorDesc()); + Log->Write("ERROR: \t could not parse the routing file [%s]",filename.c_str()); + exit(EXIT_FAILURE); + } - TiXmlElement* xRootNode = docRouting.RootElement(); - if( ! xRootNode ) { - Log->Write("ERROR:\tRoot element does not exist"); - exit(EXIT_FAILURE); - } + TiXmlElement* xRootNode = docRouting.RootElement(); + if( ! xRootNode ) { + Log->Write("ERROR:\tRoot element does not exist"); + exit(EXIT_FAILURE); + } - if( xRootNode->ValueStr () != "routing" ) { - Log->Write("ERROR:\tRoot element value is not 'routing'."); - exit(EXIT_FAILURE); - } + if( xRootNode->ValueStr () != "routing" ) { + Log->Write("ERROR:\tRoot element value is not 'routing'."); + exit(EXIT_FAILURE); + } - string version = xRootNode->Attribute("version"); - if (version != JPS_VERSION) { - Log->Write("ERROR: \tOnly version %d.%d supported",JPS_VERSION_MAJOR,JPS_VERSION_MINOR); - Log->Write("ERROR: \tparsing routing file failed!"); - exit(EXIT_FAILURE); - } + string version = xRootNode->Attribute("version"); + if (version != JPS_VERSION) { + Log->Write("ERROR: \tOnly version %d.%d supported",JPS_VERSION_MAJOR,JPS_VERSION_MINOR); + Log->Write("ERROR: \tparsing routing file failed!"); + exit(EXIT_FAILURE); + } - for(TiXmlElement* xHlinesNode = xRootNode->FirstChildElement("Hlines"); xHlinesNode; - xHlinesNode = xHlinesNode->NextSiblingElement("Hlines")) { + for(TiXmlElement* xHlinesNode = xRootNode->FirstChildElement("Hlines"); xHlinesNode; + xHlinesNode = xHlinesNode->NextSiblingElement("Hlines")) { - for(TiXmlElement* hline = xHlinesNode->FirstChildElement("Hline"); hline; - hline = hline->NextSiblingElement("Hline")) { + for(TiXmlElement* hline = xHlinesNode->FirstChildElement("Hline"); hline; + hline = hline->NextSiblingElement("Hline")) { - double id = xmltof(hline->Attribute("id"), -1); - int room_id = xmltoi(hline->Attribute("room_id"), -1); - int subroom_id = xmltoi(hline->Attribute("subroom_id"), -1); + double id = xmltof(hline->Attribute("id"), -1); + int room_id = xmltoi(hline->Attribute("room_id"), -1); + int subroom_id = xmltoi(hline->Attribute("subroom_id"), -1); - double x1 = xmltof( hline->FirstChildElement("vertex")->Attribute("px")); - double y1 = xmltof( hline->FirstChildElement("vertex")->Attribute("py")); - double x2 = xmltof( hline->LastChild("vertex")->ToElement()->Attribute("px")); - double y2 = xmltof( hline->LastChild("vertex")->ToElement()->Attribute("py")); + double x1 = xmltof( hline->FirstChildElement("vertex")->Attribute("px")); + double y1 = xmltof( hline->FirstChildElement("vertex")->Attribute("py")); + double x2 = xmltof( hline->LastChild("vertex")->ToElement()->Attribute("px")); + double y2 = xmltof( hline->LastChild("vertex")->ToElement()->Attribute("py")); - Room* room = _building->GetRoom(room_id); - SubRoom* subroom = room->GetSubRoom(subroom_id); + Room* room = _building->GetRoom(room_id); + SubRoom* subroom = room->GetSubRoom(subroom_id); - //new implementation - Hline* h = new Hline(); - h->SetID(id); - h->SetPoint1(Point(x1, y1)); - h->SetPoint2(Point(x2, y2)); - h->SetRoom(room); - h->SetSubRoom(subroom); + //new implementation + Hline* h = new Hline(); + h->SetID(id); + h->SetPoint1(Point(x1, y1)); + h->SetPoint2(Point(x2, y2)); + h->SetRoom(room); + h->SetSubRoom(subroom); - _building->AddHline(h); - subroom->AddHline(h); - } - } - Log->Write("INFO:\tDone with loading extra routing information"); + _building->AddHline(h); + subroom->AddHline(h); + } + } + Log->Write("INFO:\tDone with loading extra routing information"); } diff --git a/routing/GlobalRouter.h b/routing/GlobalRouter.h index c1144f834d3e56e624fe1d4476601dd57d745c0b..5f937ce98d4a1d2bff771f8a935666bc03355850 100644 --- a/routing/GlobalRouter.h +++ b/routing/GlobalRouter.h @@ -49,145 +49,143 @@ extern OutputHandler* Log; class GlobalRouter: public Router { - public: - GlobalRouter(); - virtual ~GlobalRouter(); - - virtual void Init(Building* building); - - - virtual int FindExit(Pedestrian* p); - - /** - * Performs a check of the geometry and fixes if possible. - * NOT IMPLEMENTED - */ - void CheckInconsistencies(); - - /** - * write the graph as GV format to be used with graphviz - * @param filename - */ - void WriteGraphGV(std::string filename, int finalDestination, - const std::vector<std::string> rooms= std::vector<std::string>()); - - - protected: - - void DumpAccessPoints(int p=-1); - - /** - * @return true if the two points are in the visibility range of each other - * @note based on http://alienryderflex.com/intersect/ - */ - bool CanSeeEachother(const Point&pt1, const Point&pt2); - - /** - * @return true if the two segments are in the visibility range of each other - */ - //bool CanSeeEachOther(Crossing* c1, Crossing* c2); - - /** - * @obsolete - * return a random exit - */ - int GetBestDefaultRandomExit(Pedestrian* p); - - /** - * @return the subroom which contains both crossings. - * Null is return is there is no such subroom. - */ - SubRoom* GetCommonSubRoom(Crossing* c1, Crossing* c2); - - /** - * @return true if the element is present in the vector - */ - template<typename A> - bool IsElementInVector(const std::vector<A> &vec, A& el) { - typename std::vector<A>::const_iterator it; - it = std::find (vec.begin(), vec.end(), el); - if(it==vec.end()){ - return false; - }else{ - return true; - } - } - - /** - * Implementation of a map with a default value. - * @return the default value if the element was not found in the map - */ - template <typename K, typename V> - V GetWithDef(const std::map <K,V> & m, const K & key, const V & defval ) { - typename std::map<K,V>::const_iterator it = m.find( key ); - if ( it == m.end() ) { - return defval; - } - else { - return it->second; - } - } - - std::string concatenate(std::string const& name, int i) - { - std::stringstream s; - s << name << i; - return s.str(); - } - - /** - * - * @param ped the pedestrian - * @param goalID, the goal ID. - * @param path where to store the intermediate destination - */ - void GetPath(Pedestrian* ped, int goalID, std::vector<SubRoom*>& path); - - - /** - * return the relevant aps that lead to the pedestrian final destination - * @param ped - */ - void GetRelevantRoutesTofinalDestination(Pedestrian *ped, std::vector<AccessPoint*>& relevantAPS); - - private: - /** - * Compute the intermediate paths between the two given transitions IDs - */ - void GetPath(int transID1, int transID2); - - - - /** - * Perform the FloydWahrshal algorithm - */ - void FloydWarshall(); - - /** - * Load extra routing information e.g navigation lines - */ - void LoadRoutingInfos(const std::string &filename); - - /** - * Each router is responsible of getting the correct filename - */ - virtual std::string GetRoutingInfoFile() const; - - - - private: - int **_pathsMatrix; - double **_distMatrix; - std::vector< int > _tmpPedPath; - std::map<int,int> _map_id_to_index; - std::map<int,int> _map_index_to_id; - ///map the internal crossings/transition id to - ///the global ID (description) for that final destination - std::map<int, int> _mapIdToFinalDestination; - - protected: - std::map <int, AccessPoint*> _accessPoints; - Building *_building; +public: + GlobalRouter(); + virtual ~GlobalRouter(); + + virtual void Init(Building* building); + + + virtual int FindExit(Pedestrian* p); + + /** + * Performs a check of the geometry and fixes if possible. + * NOT IMPLEMENTED + */ + void CheckInconsistencies(); + + /** + * write the graph as GV format to be used with graphviz + * @param filename + */ + void WriteGraphGV(std::string filename, int finalDestination, + const std::vector<std::string> rooms= std::vector<std::string>()); + + +protected: + + void DumpAccessPoints(int p=-1); + + /** + * @return true if the two points are in the visibility range of each other + * @note based on http://alienryderflex.com/intersect/ + */ + bool CanSeeEachother(const Point&pt1, const Point&pt2); + + /** + * @return true if the two segments are in the visibility range of each other + */ + //bool CanSeeEachOther(Crossing* c1, Crossing* c2); + + /** + * @obsolete + * return a random exit + */ + int GetBestDefaultRandomExit(Pedestrian* p); + + /** + * @return the subroom which contains both crossings. + * Null is return is there is no such subroom. + */ + SubRoom* GetCommonSubRoom(Crossing* c1, Crossing* c2); + + /** + * @return true if the element is present in the vector + */ + template<typename A> + bool IsElementInVector(const std::vector<A> &vec, A& el) { + typename std::vector<A>::const_iterator it; + it = std::find (vec.begin(), vec.end(), el); + if(it==vec.end()) { + return false; + } else { + return true; + } + } + + /** + * Implementation of a map with a default value. + * @return the default value if the element was not found in the map + */ + template <typename K, typename V> + V GetWithDef(const std::map <K,V> & m, const K & key, const V & defval ) { + typename std::map<K,V>::const_iterator it = m.find( key ); + if ( it == m.end() ) { + return defval; + } else { + return it->second; + } + } + + std::string concatenate(std::string const& name, int i) { + std::stringstream s; + s << name << i; + return s.str(); + } + + /** + * + * @param ped the pedestrian + * @param goalID, the goal ID. + * @param path where to store the intermediate destination + */ + void GetPath(Pedestrian* ped, int goalID, std::vector<SubRoom*>& path); + + + /** + * return the relevant aps that lead to the pedestrian final destination + * @param ped + */ + void GetRelevantRoutesTofinalDestination(Pedestrian *ped, std::vector<AccessPoint*>& relevantAPS); + +private: + /** + * Compute the intermediate paths between the two given transitions IDs + */ + void GetPath(int transID1, int transID2); + + + + /** + * Perform the FloydWahrshal algorithm + */ + void FloydWarshall(); + + /** + * Load extra routing information e.g navigation lines + */ + void LoadRoutingInfos(const std::string &filename); + + /** + * Each router is responsible of getting the correct filename + */ + virtual std::string GetRoutingInfoFile() const; + + + +private: + int **_pathsMatrix; + double **_distMatrix; + std::vector< int > _tmpPedPath; + std::map<int,int> _map_id_to_index; + std::map<int,int> _map_index_to_id; + ///map the internal crossings/transition id to + ///the global ID (description) for that final destination + std::map<int, int> _mapIdToFinalDestination; + +protected: + std::map <int, AccessPoint*> _accessPoints; + Building *_building; }; diff --git a/routing/GraphRouter.cpp b/routing/GraphRouter.cpp index d7f971bb6bfb5ec826210c4b14f3de8f33c1a67e..a03190d1f22d44b8f03cc4b27493b31eda6e431c 100644 --- a/routing/GraphRouter.cpp +++ b/routing/GraphRouter.cpp @@ -17,7 +17,7 @@ using namespace std; GraphRouter::GraphRouter() { - _building=NULL; + _building=NULL; } GraphRouter::~GraphRouter() @@ -27,114 +27,111 @@ GraphRouter::~GraphRouter() int GraphRouter::FindExit(Pedestrian* p) { - //std::cout << p->Getdt() << "\n"; - - set<int> closed_doors = p->GetKnownClosedDoors(); - - if(p->GetLastDestination() == -1) { - //this is needed for initialisation - p->ChangedSubRoom(); - //Set Initial Route at the beginning - // get next destination for person in subroom (in the subroom not next to a crossing) - ExitDistance ed = g.GetGraph(closed_doors)->GetNextDestination(p); - if(!ed.GetDest()) - { - // std::cout << "DELETE " << p->GetPedIndex() << std::endl; - // building->DeletePedFromSim(p); - return -1; - } - p->SetExitIndex(ed.GetDest()->id); - p->SetExitLine(ed.GetDest()->nav_line); - return 1; - } else { - //the pedestrian at least had a route, now check if he needs a new one - //if the pedestrian changed the subroom he needs a new route - if(p->ChangedSubRoom()) { - ExitDistance ed = g.GetGraph(closed_doors)->GetNextDestination(p->GetLastDestination(), p); - - // check if the next destination is in the right subroom - // if the routing graph changes, it could happen, that the pedestrian has to turn. - if(ed.GetSubRoom()->GetRoomID() != p->GetRoomID() || ed.GetSubRoom()->GetSubRoomID() != p->GetSubRoomID()) { - p->SetExitIndex(p->GetLastDestination()); - p->SetExitLine(ed.GetSrc()->nav_line); - return 1; - } - p->SetExitIndex(ed.GetDest()->id); - p->SetExitLine(ed.GetDest()->nav_line); - return 1; - } - if(p->GetNextDestination() != -1 && !g.GetGraph(closed_doors)->GetVertex(p->GetLastDestination())) { - ExitDistance ed = g.GetGraph(closed_doors)->GetNextDestination(p); - p->SetExitIndex(ed.GetDest()->id); - p->SetExitLine(ed.GetDest()->nav_line); - } - //check if the pedestrian reached an hline - Hline * hline = dynamic_cast<Hline*>(g.GetGraph(closed_doors)->GetVertex(p->GetNextDestination())->nav_line); - if(hline) { - // check if the pedestrian is near the Line or In LIne - if(g.GetGraph(closed_doors)->GetVertex(p->GetNextDestination())->nav_line->DistTo(p->GetPos()) < J_EPS*10 || g.GetGraph(closed_doors)->GetVertex(p->GetNextDestination())->nav_line->IsInLineSegment(p->GetPos())) { - //std::cout << "new route from HLINE" << std::endl; - ExitDistance ed = g.GetGraph(closed_doors)->GetNextDestination(p->GetLastDestination(),p); - p->SetExitIndex(ed.GetDest()->id); - p->SetExitLine(ed.GetDest()->nav_line); - return 1; - } - } - Transition * transition = dynamic_cast<Transition*>(g.GetGraph(closed_doors)->GetVertex(p->GetNextDestination())->nav_line); - if(transition) { - if(!transition->IsOpen() && transition->DistTo(p->GetPos()) < 0.5) { - p->AddKnownClosedDoor(transition->GetUniqueID()); - ExitDistance ed = g.GetGraph(closed_doors)->GetNextDestination(p); - //std::cout << p->GetPedIndex() << " -- " << ed.GetDest()->id << std::endl; - p->SetExitIndex(ed.GetDest()->id); - p->SetExitLine(ed.GetDest()->nav_line); - } - } - - // share Information about closed Doors -#pragma omp critical - if(p->DoorKnowledgeCount() != 0) { - // std::cout << "ped" << p->GetPedIndex() << std::endl; - SubRoom * sub = _building->GetRoom(p->GetRoomID())->GetSubRoom(p->GetSubRoomID()); - const vector<Pedestrian*> ps = sub->GetAllPedestrians(); - for(unsigned int i = 0; i < ps.size(); i++) { - if((p->GetPos() - ps[i]->GetPos()).Norm() < J_EPS_INFO_DIST) { - if(ps[i]->GetKnownClosedDoors() != closed_doors) - { - ps[i]->MergeKnownClosedDoors(p->GetKnownDoors()); - //maybe the other pedestrian needs a new route - ExitDistance ed = g.GetGraph(ps[i]->GetKnownClosedDoors())->GetNextDestination(ps[i]); - if(!ed.GetDest()) - { - std::cout << "DELETE " << ps[i]->GetID() << std::endl; - - _building->DeletePedFromSim(ps[i]); - } else { - // FIXME: ps[i] changedsubroom has to be called to avoid to give a new route twice! - // sometimes the outher pedestrian changed the subroom and gets a new route here. after this he is looking for a new route but there is no need for. - ps[i]->ChangedSubRoom(); - ps[i]->SetExitIndex(ed.GetDest()->id); - ps[i]->SetExitLine(ed.GetDest()->nav_line); - } - } - } - } - } - return 1; - } + //std::cout << p->Getdt() << "\n"; + + set<int> closed_doors = p->GetKnownClosedDoors(); + + if(p->GetLastDestination() == -1) { + //this is needed for initialisation + p->ChangedSubRoom(); + //Set Initial Route at the beginning + // get next destination for person in subroom (in the subroom not next to a crossing) + ExitDistance ed = g.GetGraph(closed_doors)->GetNextDestination(p); + if(!ed.GetDest()) { + // std::cout << "DELETE " << p->GetPedIndex() << std::endl; + // building->DeletePedFromSim(p); + return -1; + } + p->SetExitIndex(ed.GetDest()->id); + p->SetExitLine(ed.GetDest()->nav_line); + return 1; + } else { + //the pedestrian at least had a route, now check if he needs a new one + //if the pedestrian changed the subroom he needs a new route + if(p->ChangedSubRoom()) { + ExitDistance ed = g.GetGraph(closed_doors)->GetNextDestination(p->GetLastDestination(), p); + + // check if the next destination is in the right subroom + // if the routing graph changes, it could happen, that the pedestrian has to turn. + if(ed.GetSubRoom()->GetRoomID() != p->GetRoomID() || ed.GetSubRoom()->GetSubRoomID() != p->GetSubRoomID()) { + p->SetExitIndex(p->GetLastDestination()); + p->SetExitLine(ed.GetSrc()->nav_line); + return 1; + } + p->SetExitIndex(ed.GetDest()->id); + p->SetExitLine(ed.GetDest()->nav_line); + return 1; + } + if(p->GetNextDestination() != -1 && !g.GetGraph(closed_doors)->GetVertex(p->GetLastDestination())) { + ExitDistance ed = g.GetGraph(closed_doors)->GetNextDestination(p); + p->SetExitIndex(ed.GetDest()->id); + p->SetExitLine(ed.GetDest()->nav_line); + } + //check if the pedestrian reached an hline + Hline * hline = dynamic_cast<Hline*>(g.GetGraph(closed_doors)->GetVertex(p->GetNextDestination())->nav_line); + if(hline) { + // check if the pedestrian is near the Line or In LIne + if(g.GetGraph(closed_doors)->GetVertex(p->GetNextDestination())->nav_line->DistTo(p->GetPos()) < J_EPS*10 || g.GetGraph(closed_doors)->GetVertex(p->GetNextDestination())->nav_line->IsInLineSegment(p->GetPos())) { + //std::cout << "new route from HLINE" << std::endl; + ExitDistance ed = g.GetGraph(closed_doors)->GetNextDestination(p->GetLastDestination(),p); + p->SetExitIndex(ed.GetDest()->id); + p->SetExitLine(ed.GetDest()->nav_line); + return 1; + } + } + Transition * transition = dynamic_cast<Transition*>(g.GetGraph(closed_doors)->GetVertex(p->GetNextDestination())->nav_line); + if(transition) { + if(!transition->IsOpen() && transition->DistTo(p->GetPos()) < 0.5) { + p->AddKnownClosedDoor(transition->GetUniqueID()); + ExitDistance ed = g.GetGraph(closed_doors)->GetNextDestination(p); + //std::cout << p->GetPedIndex() << " -- " << ed.GetDest()->id << std::endl; + p->SetExitIndex(ed.GetDest()->id); + p->SetExitLine(ed.GetDest()->nav_line); + } + } + + // share Information about closed Doors + #pragma omp critical + if(p->DoorKnowledgeCount() != 0) { + // std::cout << "ped" << p->GetPedIndex() << std::endl; + SubRoom * sub = _building->GetRoom(p->GetRoomID())->GetSubRoom(p->GetSubRoomID()); + const vector<Pedestrian*> ps = sub->GetAllPedestrians(); + for(unsigned int i = 0; i < ps.size(); i++) { + if((p->GetPos() - ps[i]->GetPos()).Norm() < J_EPS_INFO_DIST) { + if(ps[i]->GetKnownClosedDoors() != closed_doors) { + ps[i]->MergeKnownClosedDoors(p->GetKnownDoors()); + //maybe the other pedestrian needs a new route + ExitDistance ed = g.GetGraph(ps[i]->GetKnownClosedDoors())->GetNextDestination(ps[i]); + if(!ed.GetDest()) { + std::cout << "DELETE " << ps[i]->GetID() << std::endl; + + _building->DeletePedFromSim(ps[i]); + } else { + // FIXME: ps[i] changedsubroom has to be called to avoid to give a new route twice! + // sometimes the outher pedestrian changed the subroom and gets a new route here. after this he is looking for a new route but there is no need for. + ps[i]->ChangedSubRoom(); + ps[i]->SetExitIndex(ed.GetDest()->id); + ps[i]->SetExitLine(ed.GetDest()->nav_line); + } + } + } + } + } + return 1; + } } void GraphRouter::Init(Building* b) { - GlobalRouter::Init(b); + GlobalRouter::Init(b); - Log->Write("ERROR: GRAPHROUTER is not ready to use yet."); - _building = b; - g.init(b); + Log->Write("ERROR: GRAPHROUTER is not ready to use yet."); + _building = b; + g.init(b); - //std::cout << b->GetTransition("200E Normal Exit E3")->IsOpen() << std::endl; - // b->GetTransition("200E Normal Exit E3")->Close(); + //std::cout << b->GetTransition("200E Normal Exit E3")->IsOpen() << std::endl; + // b->GetTransition("200E Normal Exit E3")->Close(); - //std::cout << b->GetTransition("200E Normal Exit E3")->IsOpen() << std::endl; + //std::cout << b->GetTransition("200E Normal Exit E3")->IsOpen() << std::endl; } diff --git a/routing/GraphRouter.h b/routing/GraphRouter.h index 814d82c6ea56ee4ea1d9cb95c1054b3f8dc750b8..32f2f680484915ab31062f3ca4241605b480f911 100644 --- a/routing/GraphRouter.h +++ b/routing/GraphRouter.h @@ -14,17 +14,17 @@ #include "../geometry/Building.h" class GraphRouter: public GlobalRouter { - public: - GraphRouter(); - virtual ~GraphRouter(); +public: + GraphRouter(); + virtual ~GraphRouter(); - virtual int FindExit(Pedestrian* p); - virtual void Init(Building* b); + virtual int FindExit(Pedestrian* p); + virtual void Init(Building* b); - private: - RoutingGraphStorage g; - Building * _building; - const std::set<int> empty_set; +private: + RoutingGraphStorage g; + Building * _building; + const std::set<int> empty_set; }; diff --git a/routing/MeshRouter.cpp b/routing/MeshRouter.cpp index cac83e2b6e23bb42445eb44e1fc3b20f54584598..8ee66472490bef5f6e3eb599f346ddc5fba2e98f 100644 --- a/routing/MeshRouter.cpp +++ b/routing/MeshRouter.cpp @@ -14,45 +14,49 @@ using namespace std; -MeshRouter::MeshRouter() { - _building=NULL; - _meshdata=NULL; +MeshRouter::MeshRouter() +{ + _building=NULL; + _meshdata=NULL; } -MeshRouter::~MeshRouter() { - delete _meshdata; +MeshRouter::~MeshRouter() +{ + delete _meshdata; } // Debug void astar_print(bool* closedlist,bool* inopenlist,int* predlist, - unsigned int c_totalcount,int act_id,vector<pair<double,MeshCell*> >openlist){ - cout<<"----------------------------------"<<endl; - cout<<"act_id: "<<act_id<<endl; - cout<<"Closed-List"<<endl; - for(unsigned int i=0;i<c_totalcount;i++) - cout<<(closedlist[i]?"1 ":"0 "); - cout<<endl; - cout<<"Inopen-List"<<endl; - for(unsigned int i=0;i<c_totalcount;i++) - cout<<(inopenlist[i]?"1 ":"0 "); - cout<<endl; - cout<<"Predecessor-List"<<endl; - for(unsigned int i=0;i<c_totalcount;i++) - (predlist[i]!=-1?cout<<predlist[i]<<" ":cout<<"* "); - cout<<endl; - cout<<"Openlist"<<endl; - for(unsigned int i=0;i<openlist.size();i++) - cout<<openlist.at(i).second->GetID()<<"(f="<<openlist.at(i).first<<") "; - cout<<endl; - cout<<"----------------------------------"<<endl; + unsigned int c_totalcount,int act_id,vector<pair<double,MeshCell*> >openlist) +{ + cout<<"----------------------------------"<<endl; + cout<<"act_id: "<<act_id<<endl; + cout<<"Closed-List"<<endl; + for(unsigned int i=0; i<c_totalcount; i++) + cout<<(closedlist[i]?"1 ":"0 "); + cout<<endl; + cout<<"Inopen-List"<<endl; + for(unsigned int i=0; i<c_totalcount; i++) + cout<<(inopenlist[i]?"1 ":"0 "); + cout<<endl; + cout<<"Predecessor-List"<<endl; + for(unsigned int i=0; i<c_totalcount; i++) + (predlist[i]!=-1?cout<<predlist[i]<<" ":cout<<"* "); + cout<<endl; + cout<<"Openlist"<<endl; + for(unsigned int i=0; i<openlist.size(); i++) + cout<<openlist.at(i).second->GetID()<<"(f="<<openlist.at(i).first<<") "; + cout<<endl; + cout<<"----------------------------------"<<endl; } -void print_path(vector<MeshEdge*>edge_path){ - cout<<"path from start to goal"<<endl; - for(unsigned int i=0;i<edge_path.size();i++){ - cout<<edge_path.at(i)->toString()<<endl; - } +void print_path(vector<MeshEdge*>edge_path) +{ + cout<<"path from start to goal"<<endl; + for(unsigned int i=0; i<edge_path.size(); i++) { + cout<<edge_path.at(i)->toString()<<endl; + } } /* Helper for Funnel @@ -63,22 +67,23 @@ void print_path(vector<MeshEdge*>edge_path){ / 0 \ right left */ -int TestinFunnel(Point apex, Point left,Point right,Point test){ - - bool r_test=Line(apex,right).IsLeft(test); - bool l_test=Line(left,apex).IsLeft(test); - - if (r_test){ - if(l_test) - return 0; - else - return 1; - }else{ - if(l_test) - return 3; - else - return 2; - } +int TestinFunnel(Point apex, Point left,Point right,Point test) +{ + + bool r_test=Line(apex,right).IsLeft(test); + bool l_test=Line(left,apex).IsLeft(test); + + if (r_test) { + if(l_test) + return 0; + else + return 1; + } else { + if(l_test) + return 3; + else + return 2; + } } // Computes the intersection points of two circles @@ -90,38 +95,35 @@ int TestinFunnel(Point apex, Point left,Point right,Point test){ // sp1: intersection point 2 (left) int CutCircleCircle(Point mp1, double r1, Point mp2, double r2, - Point& sp1, Point& sp2) + Point& sp1, Point& sp2) { - double d, dx, dy, a, h; + double d, dx, dy, a, h; - dx = mp2.GetX() - mp1.GetX(); - dy = mp2.GetY() - mp1.GetY(); + dx = mp2.GetX() - mp1.GetX(); + dy = mp2.GetY() - mp1.GetY(); - d=(mp2-mp1).Norm(); + d=(mp2-mp1).Norm(); - if (d > r1 + r2) // no intersection - { - return (-1); - } - else if (fabs(d) < J_EPS) // same midpoint - { - return (-2); - } - //TODO: Verify formula - // esp. test if sp1 is always on the left + if (d > r1 + r2) { // no intersection + return (-1); + } else if (fabs(d) < J_EPS) { // same midpoint + return (-2); + } + //TODO: Verify formula + // esp. test if sp1 is always on the left - a = (r1 * r1 - r2 * r2 + d * d) / (2 * d); + a = (r1 * r1 - r2 * r2 + d * d) / (2 * d); - h = sqrt (r1 * r1 - a * a); + h = sqrt (r1 * r1 - a * a); - sp1.SetX(mp1.GetX() + (a/d) * dx - (h/d) * dy); - sp1.SetY(mp1.GetY() + (a/d) * dy + (h/d) * dx); + sp1.SetX(mp1.GetX() + (a/d) * dx - (h/d) * dy); + sp1.SetY(mp1.GetY() + (a/d) * dy + (h/d) * dx); - sp2.SetX(mp1.GetX() + (a/d) * dx + (h/d) * dy); - sp2.SetY(mp1.GetY() + (a/d) * dy - (h/d) * dx); + sp2.SetX(mp1.GetX() + (a/d) * dx + (h/d) * dy); + sp2.SetY(mp1.GetY() + (a/d) * dy - (h/d) * dx); - return(0); + return(0); } /* Narrows the wedge by agents radius @@ -131,849 +133,835 @@ int CutCircleCircle(Point mp1, double r1, Point mp2, double r2, * left : goal is left point (false=right) * result: shifted goal by agents radius */ -int Funnelpoint(Point start, Point goal, bool left, Point& result){ - // Thales' circle - Point mp1=(start+goal)/2; - double r1=((start-goal).Norm())/2; - Point sp1,sp2; - // TODO: radius of pedestrian - double r2= 0.3; - int success=CutCircleCircle(mp1,r1,goal,r2,sp1,sp2); - if (success==0){ - if (left){// right point - result=sp2; - } - else{ // left point - result=sp1; - } - return 0; - } - else - return -1; +int Funnelpoint(Point start, Point goal, bool left, Point& result) +{ + // Thales' circle + Point mp1=(start+goal)/2; + double r1=((start-goal).Norm())/2; + Point sp1,sp2; + // TODO: radius of pedestrian + double r2= 0.3; + int success=CutCircleCircle(mp1,r1,goal,r2,sp1,sp2); + if (success==0) { + if (left) { // right point + result=sp2; + } else { // left point + result=sp1; + } + return 0; + } else + return -1; } // Funnel for pathfinding using non-zero size agents // Moves around corners on a fixed arc -NavLine MeshRouter::FunnelRad(Point& start,Point& goal,const vector<MeshEdge*> edge_path){ - - if(edge_path.empty()){ - exit(EXIT_FAILURE); - } - else{ - Point apex=goal,use_left,use_right; - int act_cell_id=-1; - unsigned int path_ind=0; - Point point_left,point_right; // Nodes creatin the wedge - MeshCell* act_cell=_meshdata->FindCell(start,act_cell_id); - - Point p_act_ref=act_cell->GetMidpoint(); - point_left=edge_path.at(0)->GetLeft(p_act_ref); - point_right=edge_path.at(0)->GetRight(p_act_ref); - - Point point_run_left=point_left; - Point point_run_right=point_right; - - Point wedge_left,wedge_right,wedge_run_left,wedge_run_right; - Funnelpoint(start,point_left,true,wedge_left); - Funnelpoint(start,point_right,false,wedge_right); - Funnelpoint(start,point_run_left,true,wedge_run_left); - Funnelpoint(start,point_run_right,false,wedge_run_right); - - bool apex_found=false; - // lengthen the funnel at side - bool run_left=true,run_right=true; - - while(!apex_found){ - if(path_ind!=edge_path.size()){ - if(edge_path.at(path_ind)->GetCell1()==act_cell_id) - act_cell_id=edge_path.at(path_ind)->GetCell2(); - else if (edge_path.at(path_ind)->GetCell2()==act_cell_id) - act_cell_id=edge_path.at(path_ind)->GetCell1(); - else{ - Log->Write("ERROR:\t inconsistence between act_cell and edgepath"); - cout<<"act cell id="<<act_cell_id; - cout<<"Cells 1 and 2 are"<<edge_path.at(path_ind)->GetCell1()<<"and "<<edge_path.at(path_ind)->GetCell2()<<endl; - exit(EXIT_FAILURE); - } - act_cell=_meshdata->GetCellAtPos(act_cell_id); - p_act_ref=act_cell->GetMidpoint(); - //find next points for wedge - if(path_ind+1<edge_path.size()){ // Last Cell not yet reached =>Continue or node on edge - if(run_left){ - point_run_left=edge_path.at(path_ind+1)->GetLeft(p_act_ref); - - Funnelpoint(start,point_run_left,true,wedge_run_left); - } - if(run_right){ - point_run_right=edge_path.at(path_ind+1)->GetRight(p_act_ref); - - Funnelpoint(start,point_run_right,false,wedge_run_right); - } - }else{//goal in actual cell => apex= goal or node on edge - //cout<<"In else case!"<<endl; - point_run_left=goal; - point_run_right=goal; - - Funnelpoint(start,point_run_right,false,wedge_run_right); - Funnelpoint(start,point_run_left,true,wedge_run_left); - } - // Test for new Points to be in the wedge of start - // Widen Wedge per default - int test_l=1; - int test_r=3; - if(point_left!=point_run_left) - test_l=TestinFunnel(start,wedge_left,wedge_right,wedge_run_left); - if(point_right!=point_run_right) - test_r=TestinFunnel(start,wedge_left,wedge_right,wedge_run_right); - - if(test_l==0 && test_r==0){ //Narrow wedge on both sides - //cout<<"narrow wedge on both sides"<<endl; - point_left=point_run_left; - point_right=point_run_right; - Funnelpoint(start,point_left,true,wedge_left); - Funnelpoint(start,point_right,false,wedge_right); - } - else if(test_l==1 && test_r==0){// narrow right side - //cout<<"narrow right side"<<endl; - point_right=point_run_right; - Funnelpoint(start,point_right,false,wedge_right); - } - else if(test_l==0 && test_r==3){// narrow left side - //cout<<"narrow left side"<<endl; - point_left=point_run_left; - Funnelpoint(start,point_left,true,wedge_left); - } - else if(test_l==1 && test_r==1){// apex=left - //cout<<"apex=left"<<endl; - apex=point_left; - use_left=point_left; - use_right=wedge_left+wedge_left-use_left; - - apex_found=true; - } - else if(test_l==3 && test_r==3){//apex=right - //cout<<"apex=right"<<endl; - apex=point_right; - use_right=point_right; - use_left=wedge_right+wedge_right-use_right; - - apex_found=true; - } - else if(test_l==1 && test_r==3){ // Widen wedge - //cout<<"widen wedge"<<endl; - - } - else{// Corrupted data (works with walkaround) - // Uncomment ! - //Log->Write("ERROR:\tFunnel reaches undefined state test_l %d test_r %d",test_l,test_r); - - /*cout<<start.toString()<<endl; - cout<<point_left.toString()<<endl; - cout<<point_right.toString()<<endl; - cout<<wedge_left.toString()<<endl; - cout<<wedge_right.toString()<<endl; - cout<<"run"<<endl; - cout<<point_run_left.toString()<<endl; - cout<<point_run_right.toString()<<endl; - - print_path(edge_path); - exit(EXIT_FAILURE);*/ - // Walkaround - use_left=wedge_left; - use_right=wedge_right; - apex_found=true; - } - path_ind++; - }else{//After some Funnel iterations the cell containing the goal is reached; - apex_found=true; - apex=edge_path.back()->GetPoint1();//Test - - //Log->Write("Info: Goal in Funnel"); - Funnelpoint(start,goal,false,use_left); - Funnelpoint(start,goal,true,use_right); - - } - }//END WHILE - - NavLine line; - line.SetPoint1(use_left); - line.SetPoint2(use_right); - return line; - //return edge_path.at(0); - }//END IF +NavLine MeshRouter::FunnelRad(Point& start,Point& goal,const vector<MeshEdge*> edge_path) +{ + + if(edge_path.empty()) { + exit(EXIT_FAILURE); + } else { + Point apex=goal,use_left,use_right; + int act_cell_id=-1; + unsigned int path_ind=0; + Point point_left,point_right; // Nodes creatin the wedge + MeshCell* act_cell=_meshdata->FindCell(start,act_cell_id); + + Point p_act_ref=act_cell->GetMidpoint(); + point_left=edge_path.at(0)->GetLeft(p_act_ref); + point_right=edge_path.at(0)->GetRight(p_act_ref); + + Point point_run_left=point_left; + Point point_run_right=point_right; + + Point wedge_left,wedge_right,wedge_run_left,wedge_run_right; + Funnelpoint(start,point_left,true,wedge_left); + Funnelpoint(start,point_right,false,wedge_right); + Funnelpoint(start,point_run_left,true,wedge_run_left); + Funnelpoint(start,point_run_right,false,wedge_run_right); + + bool apex_found=false; + // lengthen the funnel at side + bool run_left=true,run_right=true; + + while(!apex_found) { + if(path_ind!=edge_path.size()) { + if(edge_path.at(path_ind)->GetCell1()==act_cell_id) + act_cell_id=edge_path.at(path_ind)->GetCell2(); + else if (edge_path.at(path_ind)->GetCell2()==act_cell_id) + act_cell_id=edge_path.at(path_ind)->GetCell1(); + else { + Log->Write("ERROR:\t inconsistence between act_cell and edgepath"); + cout<<"act cell id="<<act_cell_id; + cout<<"Cells 1 and 2 are"<<edge_path.at(path_ind)->GetCell1()<<"and "<<edge_path.at(path_ind)->GetCell2()<<endl; + exit(EXIT_FAILURE); + } + act_cell=_meshdata->GetCellAtPos(act_cell_id); + p_act_ref=act_cell->GetMidpoint(); + //find next points for wedge + if(path_ind+1<edge_path.size()) { // Last Cell not yet reached =>Continue or node on edge + if(run_left) { + point_run_left=edge_path.at(path_ind+1)->GetLeft(p_act_ref); + + Funnelpoint(start,point_run_left,true,wedge_run_left); + } + if(run_right) { + point_run_right=edge_path.at(path_ind+1)->GetRight(p_act_ref); + + Funnelpoint(start,point_run_right,false,wedge_run_right); + } + } else { //goal in actual cell => apex= goal or node on edge + //cout<<"In else case!"<<endl; + point_run_left=goal; + point_run_right=goal; + + Funnelpoint(start,point_run_right,false,wedge_run_right); + Funnelpoint(start,point_run_left,true,wedge_run_left); + } + // Test for new Points to be in the wedge of start + // Widen Wedge per default + int test_l=1; + int test_r=3; + if(point_left!=point_run_left) + test_l=TestinFunnel(start,wedge_left,wedge_right,wedge_run_left); + if(point_right!=point_run_right) + test_r=TestinFunnel(start,wedge_left,wedge_right,wedge_run_right); + + if(test_l==0 && test_r==0) { //Narrow wedge on both sides + //cout<<"narrow wedge on both sides"<<endl; + point_left=point_run_left; + point_right=point_run_right; + Funnelpoint(start,point_left,true,wedge_left); + Funnelpoint(start,point_right,false,wedge_right); + } else if(test_l==1 && test_r==0) { // narrow right side + //cout<<"narrow right side"<<endl; + point_right=point_run_right; + Funnelpoint(start,point_right,false,wedge_right); + } else if(test_l==0 && test_r==3) { // narrow left side + //cout<<"narrow left side"<<endl; + point_left=point_run_left; + Funnelpoint(start,point_left,true,wedge_left); + } else if(test_l==1 && test_r==1) { // apex=left + //cout<<"apex=left"<<endl; + apex=point_left; + use_left=point_left; + use_right=wedge_left+wedge_left-use_left; + + apex_found=true; + } else if(test_l==3 && test_r==3) { //apex=right + //cout<<"apex=right"<<endl; + apex=point_right; + use_right=point_right; + use_left=wedge_right+wedge_right-use_right; + + apex_found=true; + } else if(test_l==1 && test_r==3) { // Widen wedge + //cout<<"widen wedge"<<endl; + + } else { // Corrupted data (works with walkaround) + // Uncomment ! + //Log->Write("ERROR:\tFunnel reaches undefined state test_l %d test_r %d",test_l,test_r); + + /*cout<<start.toString()<<endl; + cout<<point_left.toString()<<endl; + cout<<point_right.toString()<<endl; + cout<<wedge_left.toString()<<endl; + cout<<wedge_right.toString()<<endl; + cout<<"run"<<endl; + cout<<point_run_left.toString()<<endl; + cout<<point_run_right.toString()<<endl; + + print_path(edge_path); + exit(EXIT_FAILURE);*/ + // Walkaround + use_left=wedge_left; + use_right=wedge_right; + apex_found=true; + } + path_ind++; + } else { //After some Funnel iterations the cell containing the goal is reached; + apex_found=true; + apex=edge_path.back()->GetPoint1();//Test + + //Log->Write("Info: Goal in Funnel"); + Funnelpoint(start,goal,false,use_left); + Funnelpoint(start,goal,true,use_right); + + } + }//END WHILE + + NavLine line; + line.SetPoint1(use_left); + line.SetPoint2(use_right); + return line; + //return edge_path.at(0); + }//END IF } // Just for testing do not use // Use more stable Funnelrad instead -NavLine MeshRouter::Funnel(Point& start,Point& goal,vector<MeshEdge*> edge_path)const{ - - if(edge_path.empty()){ - // Start and End Point in same Cell - cout<<"Endpoint is in current cell"<<endl; - Line goal_line(goal,goal); - return NavLine(goal_line); - } - else{ - //int goal_cell_id=-1; - //MeshCell* goal_cell=_meshdata->FindCell(goal,goal_cell_id); - - Point apex=goal; - int act_cell_id=-1; - //int loc_ind=-1; // local index of first node to be found in startphase - unsigned int path_ind=0; - Point point_left,point_right; // Nodes creatin the wedge - MeshCell* act_cell=_meshdata->FindCell(start,act_cell_id); - - Point p_act_ref=act_cell->GetMidpoint(); - point_left=edge_path.at(0)->GetLeft(p_act_ref); - point_right=edge_path.at(0)->GetRight(p_act_ref); - - //Test - //print_path(edge_path); - //cout<<"left: "<<point_left.toString()<<" right: "<<point_right.toString()<<endl; - - Point point_run_left=point_left; - Point point_run_right=point_right; - - bool apex_found=false; - // lengthen the funnel at side - bool run_left=true,run_right=true; - - while(!apex_found){ - if(path_ind!=edge_path.size()){ - if(edge_path.at(path_ind)->GetCell1()==act_cell_id) - act_cell_id=edge_path.at(path_ind)->GetCell2(); - else if (edge_path.at(path_ind)->GetCell2()==act_cell_id) - act_cell_id=edge_path.at(path_ind)->GetCell1(); - else{ - Log->Write("ERROR:\t inconsistence between act_cell and edgepath"); - cout<<"act cell id="<<act_cell_id; - cout<<"Cells 1 and 2 are"<<edge_path.at(path_ind)->GetCell1()<<"and "<<edge_path.at(path_ind)->GetCell2()<<endl; - exit(EXIT_FAILURE); - } - act_cell=_meshdata->GetCellAtPos(act_cell_id); - p_act_ref=act_cell->GetMidpoint(); - //find next points for wedge - if(path_ind+1<edge_path.size()){ // Last Cell not yet reached =>Continue or node on edge - if(run_left){ - point_run_left=edge_path.at(path_ind+1)->GetLeft(p_act_ref); - } - if(run_right){ - point_run_right=edge_path.at(path_ind+1)->GetRight(p_act_ref); - } - }else{//goal in actual cell => apex= goal or node on edge - //cout<<"In else case!"<<endl; - point_run_left=goal; - point_run_right=goal; - } - // Test for new Points to be in the wedge of start - int test_l=TestinFunnel(start,point_left,point_right,point_run_left); - int test_r=TestinFunnel(start,point_left,point_right,point_run_right); - - if(test_l==0 && test_r==0){ //Narrow wedge on both sides - //cout<<"narrow wedge on both sides"<<endl; - point_left=point_run_left; - point_right=point_run_right; - - } - else if(test_l==1 && test_r==0){// narrow right side - //cout<<"narrow right side"<<endl; - point_right=point_run_right; - - } - else if(test_l==0 && test_r==3){// narrow left side - //cout<<"narrow left side"<<endl; - point_left=point_run_left; - - } - else if(test_l==1 && test_r==1){// apex=left - //cout<<"apex=left"<<endl; - apex=point_left; - //return NavLine(Line(edge_path.at(path_ind)->GetPoint1(),edge_path.at(path_ind)->GetPoint2())); - - apex_found=true; - } - else if(test_l==3 && test_r==3){//apex=right - //cout<<"apex=right"<<endl; - apex=point_right; - //return Nav Line(Line(edge_path.at(path_ind)->GetPoint1(),edge_path.at(path_ind)->GetPoint2())); - - apex_found=true; - } - else if(test_l==1 && test_r==3){ // Widen wedge - //cout<<"widen wedge"<<endl; - - } - else{// Corrupted data - Log->Write("ERROR:\tFunnel reaches undefined state"); - exit(EXIT_FAILURE); - } - path_ind++; - }else{//After some Funnel iterations the cell containing the goal is reached; - //apex=goal; // Initialisation! - //cout<<"Funnel progressed to goal and stopped"<<endl; - apex_found=true; - apex=edge_path.back()->GetPoint1();//Test - //return NavLine(Line(edge_path.at(path_ind-1)->GetPoint1(),edge_path.at(path_ind-1)->GetPoint2())); - } - }//END WHILE - //cout<<"Funnel from"<<start.toString()<<" results in "<<apex.toString()<<endl; - - // Some kind of workaround - // First Edge which contains the found apex - bool edgefound=false; - path_ind=0; - Point p1=apex,p2=apex; - while(!edgefound){ - if(edge_path.at(path_ind)->GetPoint1()==apex){ - p1=apex; - p2=edge_path.at(path_ind)->GetPoint2(); - edgefound=true; - } - else if(edge_path.at(path_ind)->GetPoint2()==apex){ - p1=apex; - p2=edge_path.at(path_ind)->GetPoint1(); - edgefound=true; - } - path_ind++; - } - - //NavLine exitline(Line(p1,p2)); - Point p1_new=(p1-p2)*0.9+p2; - Point p2_new=(p2-p1)*0.9+p1; - NavLine exitline(Line(p1_new,p2_new)); - //cout<<"Funnel: exitline: "<<exitline.toString()<<endl; - return exitline; - - - }//END IF +NavLine MeshRouter::Funnel(Point& start,Point& goal,vector<MeshEdge*> edge_path)const +{ + + if(edge_path.empty()) { + // Start and End Point in same Cell + cout<<"Endpoint is in current cell"<<endl; + Line goal_line(goal,goal); + return NavLine(goal_line); + } else { + //int goal_cell_id=-1; + //MeshCell* goal_cell=_meshdata->FindCell(goal,goal_cell_id); + + Point apex=goal; + int act_cell_id=-1; + //int loc_ind=-1; // local index of first node to be found in startphase + unsigned int path_ind=0; + Point point_left,point_right; // Nodes creatin the wedge + MeshCell* act_cell=_meshdata->FindCell(start,act_cell_id); + + Point p_act_ref=act_cell->GetMidpoint(); + point_left=edge_path.at(0)->GetLeft(p_act_ref); + point_right=edge_path.at(0)->GetRight(p_act_ref); + + //Test + //print_path(edge_path); + //cout<<"left: "<<point_left.toString()<<" right: "<<point_right.toString()<<endl; + + Point point_run_left=point_left; + Point point_run_right=point_right; + + bool apex_found=false; + // lengthen the funnel at side + bool run_left=true,run_right=true; + + while(!apex_found) { + if(path_ind!=edge_path.size()) { + if(edge_path.at(path_ind)->GetCell1()==act_cell_id) + act_cell_id=edge_path.at(path_ind)->GetCell2(); + else if (edge_path.at(path_ind)->GetCell2()==act_cell_id) + act_cell_id=edge_path.at(path_ind)->GetCell1(); + else { + Log->Write("ERROR:\t inconsistence between act_cell and edgepath"); + cout<<"act cell id="<<act_cell_id; + cout<<"Cells 1 and 2 are"<<edge_path.at(path_ind)->GetCell1()<<"and "<<edge_path.at(path_ind)->GetCell2()<<endl; + exit(EXIT_FAILURE); + } + act_cell=_meshdata->GetCellAtPos(act_cell_id); + p_act_ref=act_cell->GetMidpoint(); + //find next points for wedge + if(path_ind+1<edge_path.size()) { // Last Cell not yet reached =>Continue or node on edge + if(run_left) { + point_run_left=edge_path.at(path_ind+1)->GetLeft(p_act_ref); + } + if(run_right) { + point_run_right=edge_path.at(path_ind+1)->GetRight(p_act_ref); + } + } else { //goal in actual cell => apex= goal or node on edge + //cout<<"In else case!"<<endl; + point_run_left=goal; + point_run_right=goal; + } + // Test for new Points to be in the wedge of start + int test_l=TestinFunnel(start,point_left,point_right,point_run_left); + int test_r=TestinFunnel(start,point_left,point_right,point_run_right); + + if(test_l==0 && test_r==0) { //Narrow wedge on both sides + //cout<<"narrow wedge on both sides"<<endl; + point_left=point_run_left; + point_right=point_run_right; + + } else if(test_l==1 && test_r==0) { // narrow right side + //cout<<"narrow right side"<<endl; + point_right=point_run_right; + + } else if(test_l==0 && test_r==3) { // narrow left side + //cout<<"narrow left side"<<endl; + point_left=point_run_left; + + } else if(test_l==1 && test_r==1) { // apex=left + //cout<<"apex=left"<<endl; + apex=point_left; + //return NavLine(Line(edge_path.at(path_ind)->GetPoint1(),edge_path.at(path_ind)->GetPoint2())); + + apex_found=true; + } else if(test_l==3 && test_r==3) { //apex=right + //cout<<"apex=right"<<endl; + apex=point_right; + //return Nav Line(Line(edge_path.at(path_ind)->GetPoint1(),edge_path.at(path_ind)->GetPoint2())); + + apex_found=true; + } else if(test_l==1 && test_r==3) { // Widen wedge + //cout<<"widen wedge"<<endl; + + } else { // Corrupted data + Log->Write("ERROR:\tFunnel reaches undefined state"); + exit(EXIT_FAILURE); + } + path_ind++; + } else { //After some Funnel iterations the cell containing the goal is reached; + //apex=goal; // Initialisation! + //cout<<"Funnel progressed to goal and stopped"<<endl; + apex_found=true; + apex=edge_path.back()->GetPoint1();//Test + //return NavLine(Line(edge_path.at(path_ind-1)->GetPoint1(),edge_path.at(path_ind-1)->GetPoint2())); + } + }//END WHILE + //cout<<"Funnel from"<<start.toString()<<" results in "<<apex.toString()<<endl; + + // Some kind of workaround + // First Edge which contains the found apex + bool edgefound=false; + path_ind=0; + Point p1=apex,p2=apex; + while(!edgefound) { + if(edge_path.at(path_ind)->GetPoint1()==apex) { + p1=apex; + p2=edge_path.at(path_ind)->GetPoint2(); + edgefound=true; + } else if(edge_path.at(path_ind)->GetPoint2()==apex) { + p1=apex; + p2=edge_path.at(path_ind)->GetPoint1(); + edgefound=true; + } + path_ind++; + } + + //NavLine exitline(Line(p1,p2)); + Point p1_new=(p1-p2)*0.9+p2; + Point p2_new=(p2-p1)*0.9+p1; + NavLine exitline(Line(p1_new,p2_new)); + //cout<<"Funnel: exitline: "<<exitline.toString()<<endl; + return exitline; + + + }//END IF } -MeshEdge* MeshRouter::Visibility(Point& start,Point& goal,vector<MeshEdge*> edge_path)const{ - - //return *(edge_path.begin()); - if(edge_path.empty()){ - exit(EXIT_FAILURE); - }else{ - - int act_cell_id=-1; - Point point_left,point_right; // Nodes creatin the wedge - MeshCell* act_cell=_meshdata->FindCell(start,act_cell_id); - - Point p_act_ref=act_cell->GetMidpoint(); - point_left=edge_path.at(0)->GetLeft(p_act_ref); - point_right=edge_path.at(0)->GetRight(p_act_ref); - - Point point_run_left=point_left; - Point point_run_right=point_right; - - bool mesh_edge_found=false; - - MeshEdge* act_edge=edge_path.at(0); - unsigned int mesh_pos=1; - while(!mesh_edge_found && mesh_pos<edge_path.size()){ - //cout<<mesh_pos<<endl; - - point_run_left=edge_path.at(mesh_pos)->GetLeft(p_act_ref); - point_run_right=edge_path.at(mesh_pos)->GetRight(p_act_ref); - - int test_l=TestinFunnel(start,point_left,point_right,point_run_left); - int test_r=TestinFunnel(start,point_left,point_right,point_run_right); - - if(point_left==point_run_left) - test_l=0; - else if (point_right==point_run_right) - test_r=0; - - if(test_l==0 && test_r==0){ //Narrow wedge on both sides - //cout<<"narrow wedge on both sides"<<endl; - point_left=point_run_left; - point_right=point_run_right; - }else{ - act_edge=edge_path.at(mesh_pos-1); - mesh_edge_found=true; - } - mesh_pos++; - } - //cout<<"The next edge is: "<<act_edge->toString()<<endl; - return act_edge; - return edge_path.at(0); - } +MeshEdge* MeshRouter::Visibility(Point& start,Point& goal,vector<MeshEdge*> edge_path)const +{ + + //return *(edge_path.begin()); + if(edge_path.empty()) { + exit(EXIT_FAILURE); + } else { + + int act_cell_id=-1; + Point point_left,point_right; // Nodes creatin the wedge + MeshCell* act_cell=_meshdata->FindCell(start,act_cell_id); + + Point p_act_ref=act_cell->GetMidpoint(); + point_left=edge_path.at(0)->GetLeft(p_act_ref); + point_right=edge_path.at(0)->GetRight(p_act_ref); + + Point point_run_left=point_left; + Point point_run_right=point_right; + + bool mesh_edge_found=false; + + MeshEdge* act_edge=edge_path.at(0); + unsigned int mesh_pos=1; + while(!mesh_edge_found && mesh_pos<edge_path.size()) { + //cout<<mesh_pos<<endl; + + point_run_left=edge_path.at(mesh_pos)->GetLeft(p_act_ref); + point_run_right=edge_path.at(mesh_pos)->GetRight(p_act_ref); + + int test_l=TestinFunnel(start,point_left,point_right,point_run_left); + int test_r=TestinFunnel(start,point_left,point_right,point_run_right); + + if(point_left==point_run_left) + test_l=0; + else if (point_right==point_run_right) + test_r=0; + + if(test_l==0 && test_r==0) { //Narrow wedge on both sides + //cout<<"narrow wedge on both sides"<<endl; + point_left=point_run_left; + point_right=point_run_right; + } else { + act_edge=edge_path.at(mesh_pos-1); + mesh_edge_found=true; + } + mesh_pos++; + } + //cout<<"The next edge is: "<<act_edge->toString()<<endl; + return act_edge; + return edge_path.at(0); + } } -vector<MeshEdge*> MeshRouter::AStar(Pedestrian* p,int& status)const{ - - // Path from start to goal through this edges - vector<MeshEdge*> pathedge; - - int c_start_id; - //Point testp_start(0,0); - Point p_start=p->GetPos(); - //cout<<testp_start.toString()<<endl;; - MeshCell* start_cell=_meshdata->FindCell(p_start,c_start_id); - if(start_cell!=NULL){ - //cout<<testp_start.toString()<<"Found in cell "<<c_start_id<<endl; - } - else{ - Log->Write("Startpoint not found"); - std::cout.precision(10); - std::cout.setf( std::ios::fixed, std:: ios::floatfield ); - cout<<"startpoint: "<< p_start.GetX()<<" "<<p_start.GetY()<<"of pedestrian: "<<p->GetID()<<endl; - exit(EXIT_FAILURE); - } - int c_goal_id; - Point point_goal = _building->GetFinalGoal(p->GetFinalDestination())->GetCentroid(); - //cout<<"here"<<endl; - MeshCell* goal_cell=_meshdata->FindCell(point_goal,c_goal_id); - if(goal_cell!=NULL){ - //cout<<testp_goal.toString()<<"Found in cell: "<<c_goal_id<<endl;// - } - else{ - cout<<"Goal not found"<<endl; - } - - - //Initialisation - unsigned int c_totalcount=_meshdata->GetCellCount(); - //cout<<"Total Number of Cells: "<<c_totalcount<<endl; - bool* closedlist=new bool[c_totalcount]; - bool* inopenlist=new bool[c_totalcount]; - int* predlist=new int[c_totalcount]; // to gain the path from start to goal - MeshEdge ** predEdgelist=new MeshEdge*[c_totalcount]; - double* costlist=new double[c_totalcount]; - for(unsigned int i=0;i<c_totalcount;i++){ - closedlist[i]=false; - inopenlist[i]=false; - predlist[i]=-1; - } - - MeshCell* act_cell=start_cell; - int act_id=c_start_id; - double f= (act_cell->GetMidpoint()-point_goal).Norm(); - double act_cost=f; - vector<pair< double , MeshCell*> > openlist; - openlist.push_back(make_pair(f,start_cell)); - costlist[act_id]=f; - inopenlist[c_start_id]=true; - - while(act_id!=c_goal_id){ - act_cost=costlist[act_id]; - //astar_print(closedlist,inopenlist,predlist,c_totalcount,act_id); - if (act_cell==NULL) - cout<<"act_cell=NULL !!"<<endl; - - for(unsigned int i=0;i<act_cell->GetEdges().size();i++){ - int act_edge_id=act_cell->GetEdges().at(i); - MeshEdge* act_edge=_meshdata->GetEdges().at(act_edge_id); - int nb_id=-1; - // Find neighbouring cell - - if(act_edge->GetCell1()==act_id){ - nb_id=act_edge->GetCell2(); - } - else if(act_edge->GetCell2()==act_id){ - nb_id=act_edge->GetCell1(); - } - else{// Error: inconsistant - Log->Write("Error:\tInconsistant Mesh-Data"); - } - int n1_pos=act_edge->GetNode1(); - int n2_pos=act_edge->GetNode2(); - Point p1_p=*_meshdata->GetNodes().at(n1_pos); - Point p2_p=*_meshdata->GetNodes().at(n2_pos); - double length=(p1_p-p2_p).Norm(); - MeshCell* nb_cell=_meshdata->GetCellAtPos(nb_id); - // Calculate - if (nb_cell->GetEdges().size()==3){ - - } - if (!closedlist[nb_id] && length>0.2){// neighbour-cell not fully evaluated - //MeshCell* nb_cell=_meshdata->GetCellAtPos(nb_id); - double new_cost=act_cost+(act_cell->GetMidpoint()-nb_cell->GetMidpoint()).Norm(); - if(!inopenlist[nb_id]){// neighbour-cell not evaluated at all - predlist[nb_id]=act_id; - //predEdgelist[nb_id]=_meshdata->GetEdges().at(act_edge_id); - predEdgelist[nb_id]=act_edge; - costlist[nb_id]=new_cost; - inopenlist[nb_id]=true; +vector<MeshEdge*> MeshRouter::AStar(Pedestrian* p,int& status)const +{ + // Path from start to goal through this edges + vector<MeshEdge*> pathedge; + + int c_start_id; + //Point testp_start(0,0); + Point p_start=p->GetPos(); + //cout<<testp_start.toString()<<endl;; + MeshCell* start_cell=_meshdata->FindCell(p_start,c_start_id); + if(start_cell!=NULL) { + //cout<<testp_start.toString()<<"Found in cell "<<c_start_id<<endl; + } else { + Log->Write("Startpoint not found"); + std::cout.precision(10); + std::cout.setf( std::ios::fixed, std:: ios::floatfield ); + cout<<"startpoint: "<< p_start.GetX()<<" "<<p_start.GetY()<<"of pedestrian: "<<p->GetID()<<endl; + exit(EXIT_FAILURE); + } + int c_goal_id; + Point point_goal = _building->GetFinalGoal(p->GetFinalDestination())->GetCentroid(); + //cout<<"here"<<endl; + MeshCell* goal_cell=_meshdata->FindCell(point_goal,c_goal_id); + if(goal_cell!=NULL) { + //cout<<testp_goal.toString()<<"Found in cell: "<<c_goal_id<<endl;// + } else { + cout<<"Goal not found"<<endl; + } + + + //Initialisation + unsigned int c_totalcount=_meshdata->GetCellCount(); + //cout<<"Total Number of Cells: "<<c_totalcount<<endl; + bool* closedlist=new bool[c_totalcount]; + bool* inopenlist=new bool[c_totalcount]; + int* predlist=new int[c_totalcount]; // to gain the path from start to goal + MeshEdge ** predEdgelist=new MeshEdge*[c_totalcount]; + double* costlist=new double[c_totalcount]; + for(unsigned int i=0; i<c_totalcount; i++) { + closedlist[i]=false; + inopenlist[i]=false; + predlist[i]=-1; + } + + MeshCell* act_cell=start_cell; + int act_id=c_start_id; + double f= (act_cell->GetMidpoint()-point_goal).Norm(); + double act_cost=f; + vector<pair< double , MeshCell*> > openlist; + openlist.push_back(make_pair(f,start_cell)); + costlist[act_id]=f; + inopenlist[c_start_id]=true; + + while(act_id!=c_goal_id) { + act_cost=costlist[act_id]; + //astar_print(closedlist,inopenlist,predlist,c_totalcount,act_id); + if (act_cell==NULL) + cout<<"act_cell=NULL !!"<<endl; + + for(unsigned int i=0; i<act_cell->GetEdges().size(); i++) { + int act_edge_id=act_cell->GetEdges().at(i); + MeshEdge* act_edge=_meshdata->GetEdges().at(act_edge_id); + int nb_id=-1; + // Find neighbouring cell + + if(act_edge->GetCell1()==act_id) { + nb_id=act_edge->GetCell2(); + } else if(act_edge->GetCell2()==act_id) { + nb_id=act_edge->GetCell1(); + } else { // Error: inconsistant + Log->Write("Error:\tInconsistant Mesh-Data"); + } + int n1_pos=act_edge->GetNode1(); + int n2_pos=act_edge->GetNode2(); + Point p1_p=*_meshdata->GetNodes().at(n1_pos); + Point p2_p=*_meshdata->GetNodes().at(n2_pos); + double length=(p1_p-p2_p).Norm(); + MeshCell* nb_cell=_meshdata->GetCellAtPos(nb_id); + // Calculate + if (nb_cell->GetEdges().size()==3) { + + } + if (!closedlist[nb_id] && length>0.2) { // neighbour-cell not fully evaluated + //MeshCell* nb_cell=_meshdata->GetCellAtPos(nb_id); + double new_cost=act_cost+(act_cell->GetMidpoint()-nb_cell->GetMidpoint()).Norm(); + if(!inopenlist[nb_id]) { // neighbour-cell not evaluated at all + predlist[nb_id]=act_id; + //predEdgelist[nb_id]=_meshdata->GetEdges().at(act_edge_id); + predEdgelist[nb_id]=act_edge; + costlist[nb_id]=new_cost; + inopenlist[nb_id]=true; + + double f=new_cost+(nb_cell->GetMidpoint()-point_goal).Norm(); + openlist.push_back(make_pair(f,nb_cell)); + } else { + if (new_cost<costlist[nb_id]) { + //cout<<"ERROR"<<endl; + //found shorter path to nb_cell + predlist[nb_id]=act_id; + costlist[nb_id]=new_cost; + // update nb in openlist + for(unsigned int j=0; j<openlist.size(); j++) { + if(openlist.at(i).second->GetID()==nb_id) { + MeshCell* nb_cell=openlist.at(i).second; double f=new_cost+(nb_cell->GetMidpoint()-point_goal).Norm(); - openlist.push_back(make_pair(f,nb_cell)); - } - else{ - if (new_cost<costlist[nb_id]){ - //cout<<"ERROR"<<endl; - //found shorter path to nb_cell - predlist[nb_id]=act_id; - costlist[nb_id]=new_cost; - // update nb in openlist - for(unsigned int j=0;j<openlist.size();j++){ - if(openlist.at(i).second->GetID()==nb_id){ - MeshCell* nb_cell=openlist.at(i).second; - double f=new_cost+(nb_cell->GetMidpoint()-point_goal).Norm(); - openlist.at(i)=make_pair(f,nb_cell); - break; - } - } - } - else{ - // Do nothing: Path is worse - } - } - } - } - - vector<pair<double,MeshCell*> >::iterator it=openlist.begin(); - - while(it->second->GetID()!=act_id){ - it++; - } - closedlist[act_id]=true; - inopenlist[act_id]=false; - openlist.erase(it); - - int next_cell_id=-1; - MeshCell* next_cell=NULL; - //astar_print(closedlist,inopenlist,predlist,c_totalcount,act_id,openlist); /////////////// - if (openlist.size()>0){ - //Find cell with best f value - double min_f=openlist.at(0).first; - next_cell_id=openlist.at(0).second->GetID(); - //cout<<"next_cell_id: "<<next_cell_id<<endl; - next_cell=openlist.at(0).second; - for(unsigned int j=1;j<openlist.size();j++){ - if (openlist.at(j).first<min_f){ - min_f=openlist.at(j).first; - next_cell=openlist.at(j).second; - next_cell_id=openlist.at(j).second->GetID(); - } - } - act_id=next_cell_id; - act_cell=next_cell; - } - else{ - Log->Write("Error:\tA* did not find a path"); - } - } - delete[] closedlist; - delete[] inopenlist; - delete[] costlist; - //print_path(predlist,c_start_id,c_goal_id);///////////////// - //astar_print(closedlist,inopenlist,predlist,c_totalcount,act_id,openlist); - - // In the case the agent is in the destination cell - if(predlist[c_goal_id]==-1){ - status=-1; - return pathedge; - } - - // Building the path reversely from goal to start - act_id=c_goal_id; - while(predlist[act_id]!=c_start_id){ - pathedge.push_back(predEdgelist[act_id]); - act_id=predlist[act_id]; - } - - if(predlist[act_id]==c_start_id) - pathedge.push_back(predEdgelist[act_id]); - - delete[] predlist; - delete[] predEdgelist; - - // Reverse the reversed path - std::reverse(pathedge.begin(),pathedge.end()); - - status=0; - return pathedge; + openlist.at(i)=make_pair(f,nb_cell); + break; + } + } + } else { + // Do nothing: Path is worse + } + } + } + } + + vector<pair<double,MeshCell*> >::iterator it=openlist.begin(); + + while(it->second->GetID()!=act_id) { + it++; + } + closedlist[act_id]=true; + inopenlist[act_id]=false; + openlist.erase(it); + + int next_cell_id=-1; + MeshCell* next_cell=NULL; + //astar_print(closedlist,inopenlist,predlist,c_totalcount,act_id,openlist); /////////////// + if (openlist.size()>0) { + //Find cell with best f value + double min_f=openlist.at(0).first; + next_cell_id=openlist.at(0).second->GetID(); + //cout<<"next_cell_id: "<<next_cell_id<<endl; + next_cell=openlist.at(0).second; + for(unsigned int j=1; j<openlist.size(); j++) { + if (openlist.at(j).first<min_f) { + min_f=openlist.at(j).first; + next_cell=openlist.at(j).second; + next_cell_id=openlist.at(j).second->GetID(); + } + } + act_id=next_cell_id; + act_cell=next_cell; + } else { + Log->Write("Error:\tA* did not find a path"); + } + } + delete[] closedlist; + delete[] inopenlist; + delete[] costlist; + //print_path(predlist,c_start_id,c_goal_id);///////////////// + //astar_print(closedlist,inopenlist,predlist,c_totalcount,act_id,openlist); + + // In the case the agent is in the destination cell + if(predlist[c_goal_id]==-1) { + status=-1; + return pathedge; + } + + // Building the path reversely from goal to start + act_id=c_goal_id; + while(predlist[act_id]!=c_start_id) { + pathedge.push_back(predEdgelist[act_id]); + act_id=predlist[act_id]; + } + + if(predlist[act_id]==c_start_id) + pathedge.push_back(predEdgelist[act_id]); + + delete[] predlist; + delete[] predEdgelist; + + // Reverse the reversed path + std::reverse(pathedge.begin(),pathedge.end()); + + status=0; + return pathedge; } -int MeshRouter::FindExit(Pedestrian* p){ - //cout<<"calling the mesh router"<<endl; - Point point_start=p->GetPos(); - int c_start_id=-1; - _meshdata->FindCell(point_start,c_start_id); - //MeshEdge* edge=NULL; - NavLine* nextline=NULL; - NavLine line; - //MeshEdge* meshline=NULL; - - - if (false){// Compute the goal each update - //if(p->GetCellPos()==c_start_id){ - nextline=p->GetExitLine(); - }else{ - int status=-1; - //cout<<"before A*"<<endl; - vector<MeshEdge*> edgepath=AStar(p,status); - //cout<<"after A*"<<endl; - if (status==-1) return -1; - if(edgepath.empty()){ - Log->Write("Path is empty but next edge is defined"); - exit(EXIT_FAILURE); - } - - //TODO: save the point goal in the ped class - Point point_goal = _building->GetFinalGoal(p->GetFinalDestination())->GetCentroid(); - //cout<<"Goal: "<<point_goal.toString()<<endl; - //line=Funnel(point_start,point_goal,edgepath); - bool funnel=false; - if(funnel){ - line=Funnel(point_start,point_goal,edgepath); - if(line.GetPoint1()==line.GetPoint2()){ - Log->Write("ERROR:\tNavLine is a point"); - //cout<<"This point is: "<<line.GetPoint1().toString()<<endl; - exit(EXIT_FAILURE); - }else{ - //cout<<"The line is: "<<line.toString()<<endl; - } - nextline=&line; - }else{ - - //Point use_left,use_right; - //meshline=FunnelRad(point_start,point_goal,edgepath,use_left,use_right); - line=FunnelRad(point_start,point_goal,edgepath); - - nextline=&line; - - } - if(nextline==NULL){ - Log->Write("Edge is corrupt"); - exit(EXIT_FAILURE); - } - }// END ELSE - - p->SetExitLine(nextline); - //p->SetCellPos(c_start_id); - return 0; +int MeshRouter::FindExit(Pedestrian* p) +{ + //cout<<"calling the mesh router"<<endl; + Point point_start=p->GetPos(); + int c_start_id=-1; + _meshdata->FindCell(point_start,c_start_id); + //MeshEdge* edge=NULL; + NavLine* nextline=NULL; + NavLine line; + //MeshEdge* meshline=NULL; + + + if (false) { // Compute the goal each update + //if(p->GetCellPos()==c_start_id){ + nextline=p->GetExitLine(); + } else { + int status=-1; + //cout<<"before A*"<<endl; + vector<MeshEdge*> edgepath=AStar(p,status); + //cout<<"after A*"<<endl; + if (status==-1) return -1; + if(edgepath.empty()) { + Log->Write("Path is empty but next edge is defined"); + exit(EXIT_FAILURE); + } + + //TODO: save the point goal in the ped class + Point point_goal = _building->GetFinalGoal(p->GetFinalDestination())->GetCentroid(); + //cout<<"Goal: "<<point_goal.toString()<<endl; + //line=Funnel(point_start,point_goal,edgepath); + bool funnel=false; + if(funnel) { + line=Funnel(point_start,point_goal,edgepath); + if(line.GetPoint1()==line.GetPoint2()) { + Log->Write("ERROR:\tNavLine is a point"); + //cout<<"This point is: "<<line.GetPoint1().toString()<<endl; + exit(EXIT_FAILURE); + } else { + //cout<<"The line is: "<<line.toString()<<endl; + } + nextline=&line; + } else { + + //Point use_left,use_right; + //meshline=FunnelRad(point_start,point_goal,edgepath,use_left,use_right); + line=FunnelRad(point_start,point_goal,edgepath); + + nextline=&line; + + } + if(nextline==NULL) { + Log->Write("Edge is corrupt"); + exit(EXIT_FAILURE); + } + }// END ELSE + + p->SetExitLine(nextline); + //p->SetCellPos(c_start_id); + return 0; } -void MeshRouter::FixMeshEdges(){ - for(unsigned int i=0;i<_meshdata->GetEdges().size();i++){ - - MeshEdge* edge=_meshdata->GetEdges().at(i); - for (map<int, Crossing*>::const_iterator itr = _building->GetAllCrossings().begin(); - itr != _building->GetAllCrossings().end(); ++itr) { - - //int door=itr->first; - //int door = itr->second->GetUniqueID(); - Crossing* cross = itr->second; - if(edge->operator ==(*cross)){ - edge->SetRoom1(cross->GetRoom1()); - edge->SetSubRoom1(cross->GetSubRoom1()); - edge->SetSubRoom2(cross->GetSubRoom2()); - - } - } - for (map<int, Transition*>::const_iterator itr = _building->GetAllTransitions().begin(); - itr != _building->GetAllTransitions().end(); ++itr) { - - //int door=itr->first; - //int door = itr->second->GetUniqueID(); - Transition* cross = itr->second; - //const Point& centre = cross->GetCentre(); - //double center[2] = { centre.GetX(), centre.GetY() }; - if(edge->operator ==(*cross)){ - edge->SetRoom1(cross->GetRoom1()); - //edge->SetRoom2(cross->GetRoom2()); - edge->SetSubRoom1(cross->GetSubRoom1()); - edge->SetSubRoom2(cross->GetSubRoom2()); - } - } - } - - // int size=_meshdata->Get_outEdges().size(); - // for(int i=0;i<size;i++){ - // MeshEdge* edge=_meshdata->Get_outEdges().at(i); - // for (map<int, Crossing*>::const_iterator itr = _building->GetAllCrossings().begin(); - // itr != _building->GetAllCrossings().end(); ++itr) { - // - // //int door=itr->first; - // int door = itr->second->GetUniqueID(); - // Crossing* cross = itr->second; - // if(edge->operator ==(*cross)){ - // edge->SetRoom1(cross->GetRoom1()); - // edge->SetSubRoom1(cross->GetSubRoom1()); - // edge->SetSubRoom2(cross->GetSubRoom2()); - // - // } - // } - // for (map<int, Transition*>::const_iterator itr = _building->GetAllTransitions().begin(); - // itr != _building->GetAllTransitions().end(); ++itr) { - // - //// int door=itr->first; - // int door = itr->second->GetUniqueID(); - // Transition* cross = itr->second; - // const Point& centre = cross->GetCentre(); - // double center[2] = { centre.GetX(), centre.GetY() }; - // if(edge->operator ==(*cross)){ - // edge->SetRoom1(cross->GetRoom1()); - // edge->SetSubRoom1(cross->GetSubRoom1()); - // edge->SetSubRoom2(cross->GetSubRoom2()); - // } - // } - // } - - for(unsigned int i=0;i<_meshdata->GetEdges().size();i++){ - MeshEdge* edge=_meshdata->GetEdges().at(i); - if(edge->GetRoom1()==NULL){ - - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* room = _building->GetRoom(i); - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - if(sub->IsInSubRoom( edge->GetCentre())){ - edge->SetSubRoom1(sub); - edge->SetSubRoom2(sub); - edge->SetRoom1(room); - } - } - } - } - } - for(unsigned int i=0;i<_meshdata->GetEdges().size();i++){ - MeshEdge* edge=_meshdata->GetEdges().at(i); - if(edge->GetRoom1()==NULL){ - exit(EXIT_FAILURE); - } - } +void MeshRouter::FixMeshEdges() +{ + for(unsigned int i=0; i<_meshdata->GetEdges().size(); i++) { + + MeshEdge* edge=_meshdata->GetEdges().at(i); + for (map<int, Crossing*>::const_iterator itr = _building->GetAllCrossings().begin(); + itr != _building->GetAllCrossings().end(); ++itr) { + + //int door=itr->first; + //int door = itr->second->GetUniqueID(); + Crossing* cross = itr->second; + if(edge->operator ==(*cross)) { + edge->SetRoom1(cross->GetRoom1()); + edge->SetSubRoom1(cross->GetSubRoom1()); + edge->SetSubRoom2(cross->GetSubRoom2()); + + } + } + for (map<int, Transition*>::const_iterator itr = _building->GetAllTransitions().begin(); + itr != _building->GetAllTransitions().end(); ++itr) { + + //int door=itr->first; + //int door = itr->second->GetUniqueID(); + Transition* cross = itr->second; + //const Point& centre = cross->GetCentre(); + //double center[2] = { centre.GetX(), centre.GetY() }; + if(edge->operator ==(*cross)) { + edge->SetRoom1(cross->GetRoom1()); + //edge->SetRoom2(cross->GetRoom2()); + edge->SetSubRoom1(cross->GetSubRoom1()); + edge->SetSubRoom2(cross->GetSubRoom2()); + } + } + } + + // int size=_meshdata->Get_outEdges().size(); + // for(int i=0;i<size;i++){ + // MeshEdge* edge=_meshdata->Get_outEdges().at(i); + // for (map<int, Crossing*>::const_iterator itr = _building->GetAllCrossings().begin(); + // itr != _building->GetAllCrossings().end(); ++itr) { + // + // //int door=itr->first; + // int door = itr->second->GetUniqueID(); + // Crossing* cross = itr->second; + // if(edge->operator ==(*cross)){ + // edge->SetRoom1(cross->GetRoom1()); + // edge->SetSubRoom1(cross->GetSubRoom1()); + // edge->SetSubRoom2(cross->GetSubRoom2()); + // + // } + // } + // for (map<int, Transition*>::const_iterator itr = _building->GetAllTransitions().begin(); + // itr != _building->GetAllTransitions().end(); ++itr) { + // + //// int door=itr->first; + // int door = itr->second->GetUniqueID(); + // Transition* cross = itr->second; + // const Point& centre = cross->GetCentre(); + // double center[2] = { centre.GetX(), centre.GetY() }; + // if(edge->operator ==(*cross)){ + // edge->SetRoom1(cross->GetRoom1()); + // edge->SetSubRoom1(cross->GetSubRoom1()); + // edge->SetSubRoom2(cross->GetSubRoom2()); + // } + // } + // } + + for(unsigned int i=0; i<_meshdata->GetEdges().size(); i++) { + MeshEdge* edge=_meshdata->GetEdges().at(i); + if(edge->GetRoom1()==NULL) { + + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* room = _building->GetRoom(i); + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + if(sub->IsInSubRoom( edge->GetCentre())) { + edge->SetSubRoom1(sub); + edge->SetSubRoom2(sub); + edge->SetRoom1(room); + } + } + } + } + } + for(unsigned int i=0; i<_meshdata->GetEdges().size(); i++) { + MeshEdge* edge=_meshdata->GetEdges().at(i); + if(edge->GetRoom1()==NULL) { + exit(EXIT_FAILURE); + } + } } -void MeshRouter::Init(Building* b) { - _building=b; - //Log->Write("WARNING: \tdo not use this <<Mesh>> router !!"); - - string meshfileName=GetMeshFileName(); - ifstream meshfiled; - meshfiled.open(meshfileName.c_str(), ios::in); - if(!meshfiled.is_open()){ - Log->Write("ERROR: \tcould not open meshfile <%s>",meshfileName.c_str()); - exit(EXIT_FAILURE); - } - stringstream meshfile; - meshfile<<meshfiled.rdbuf(); - meshfiled.close(); - - vector<Point*> nodes; //nodes.clear(); - vector<MeshEdge*> edges; - vector<MeshEdge*> outedges; - vector<MeshCellGroup*> mCellGroups; - - unsigned int countNodes=0; - meshfile>>countNodes; - for(unsigned int i=0;i<countNodes;i++){ - double temp1,temp2; - meshfile>>temp1>>temp2; - nodes.push_back(new Point(temp1,temp2)); - } - cout<<setw(2)<<"Read "<<nodes.size()<<" Nodes from file"<<endl; - - unsigned int countEdges=0; - meshfile>>countEdges; - for(unsigned int i=0;i<countEdges;i++){ - int t1,t2,t3,t4; - meshfile>>t1>>t2>>t3>>t4; - edges.push_back(new MeshEdge(t1,t2,t3,t4,*(nodes.at(t1)),*(nodes.at(t2)))); - } - cout<<"Read "<<edges.size()<<" inner Edges from file"<<endl; - - unsigned int countOutEdges=0; - meshfile>>countOutEdges; - for(unsigned int i=0;i<countOutEdges;i++){ - int t1,t2,t3,t4; - meshfile>>t1>>t2>>t3>>t4; - outedges.push_back(new MeshEdge(t1,t2,t3,t4,*(nodes.at(t1)),*(nodes.at(t2)))); - } - cout<<"Read "<<outedges.size()<<" outer Edges from file"<<endl; - - int tc_id=0; - //int while_counter=0;// - while(!meshfile.eof()){ - //cout<<"in while(!meshfile.eof()): "<<while_counter<<endl; - string groupname; - bool namefound=false; - //TODO better rouine for skipping empty lines - while(!namefound && getline(meshfile,groupname)){ - if (groupname.size()>1){ - namefound=true; - //cout<<"groupname: "<<groupname<<endl; - } - } - if (!meshfile.eof()){ - - unsigned int countCells=0; - meshfile>>countCells; - - vector<MeshCell*> mCells; mCells.clear(); - for(unsigned int i=0;i<countCells;i++){ - double midx,midy; - meshfile>>midx>>midy; - unsigned int countNodes=0; - meshfile>>countNodes; - vector<int> node_id; - for(unsigned int j=0;j<countNodes;j++){ - int tmp; - meshfile>>tmp; - node_id.push_back(tmp); - } - //double* normvec=new double[3]; - double normvec[3]; - for (unsigned int j=0;j<3;j++){ - double tmp=0.0; - meshfile>>tmp; - normvec[j]=tmp; - } - unsigned int countEdges=0; - meshfile>>countEdges; - vector<int> edge_id; - for(unsigned int j=0;j<countEdges;j++){ - int tmp; - meshfile>>tmp; - edge_id.push_back(tmp); - } - unsigned int countWalls=0; - meshfile>>countWalls; - vector<int> wall_id; - for(unsigned int j=0;j<countWalls;j++){ - int tmp; - meshfile>>tmp; - wall_id.push_back(tmp); - } - mCells.push_back(new MeshCell(midx,midy,node_id,normvec,edge_id,wall_id,tc_id)); - tc_id++; - } - mCellGroups.push_back(new MeshCellGroup(groupname,mCells)); - } - } - _meshdata=new MeshData(nodes,edges,outedges,mCellGroups); - FixMeshEdges(); +void MeshRouter::Init(Building* b) +{ + _building=b; + //Log->Write("WARNING: \tdo not use this <<Mesh>> router !!"); + + string meshfileName=GetMeshFileName(); + ifstream meshfiled; + meshfiled.open(meshfileName.c_str(), ios::in); + if(!meshfiled.is_open()) { + Log->Write("ERROR: \tcould not open meshfile <%s>",meshfileName.c_str()); + exit(EXIT_FAILURE); + } + stringstream meshfile; + meshfile<<meshfiled.rdbuf(); + meshfiled.close(); + + vector<Point*> nodes; //nodes.clear(); + vector<MeshEdge*> edges; + vector<MeshEdge*> outedges; + vector<MeshCellGroup*> mCellGroups; + + unsigned int countNodes=0; + meshfile>>countNodes; + for(unsigned int i=0; i<countNodes; i++) { + double temp1,temp2; + meshfile>>temp1>>temp2; + nodes.push_back(new Point(temp1,temp2)); + } + cout<<setw(2)<<"Read "<<nodes.size()<<" Nodes from file"<<endl; + + unsigned int countEdges=0; + meshfile>>countEdges; + for(unsigned int i=0; i<countEdges; i++) { + int t1,t2,t3,t4; + meshfile>>t1>>t2>>t3>>t4; + edges.push_back(new MeshEdge(t1,t2,t3,t4,*(nodes.at(t1)),*(nodes.at(t2)))); + } + cout<<"Read "<<edges.size()<<" inner Edges from file"<<endl; + + unsigned int countOutEdges=0; + meshfile>>countOutEdges; + for(unsigned int i=0; i<countOutEdges; i++) { + int t1,t2,t3,t4; + meshfile>>t1>>t2>>t3>>t4; + outedges.push_back(new MeshEdge(t1,t2,t3,t4,*(nodes.at(t1)),*(nodes.at(t2)))); + } + cout<<"Read "<<outedges.size()<<" outer Edges from file"<<endl; + + int tc_id=0; + //int while_counter=0;// + while(!meshfile.eof()) { + //cout<<"in while(!meshfile.eof()): "<<while_counter<<endl; + string groupname; + bool namefound=false; + //TODO better rouine for skipping empty lines + while(!namefound && getline(meshfile,groupname)) { + if (groupname.size()>1) { + namefound=true; + //cout<<"groupname: "<<groupname<<endl; + } + } + if (!meshfile.eof()) { + + unsigned int countCells=0; + meshfile>>countCells; + + vector<MeshCell*> mCells; + mCells.clear(); + for(unsigned int i=0; i<countCells; i++) { + double midx,midy; + meshfile>>midx>>midy; + unsigned int countNodes=0; + meshfile>>countNodes; + vector<int> node_id; + for(unsigned int j=0; j<countNodes; j++) { + int tmp; + meshfile>>tmp; + node_id.push_back(tmp); + } + //double* normvec=new double[3]; + double normvec[3]; + for (unsigned int j=0; j<3; j++) { + double tmp=0.0; + meshfile>>tmp; + normvec[j]=tmp; + } + unsigned int countEdges=0; + meshfile>>countEdges; + vector<int> edge_id; + for(unsigned int j=0; j<countEdges; j++) { + int tmp; + meshfile>>tmp; + edge_id.push_back(tmp); + } + unsigned int countWalls=0; + meshfile>>countWalls; + vector<int> wall_id; + for(unsigned int j=0; j<countWalls; j++) { + int tmp; + meshfile>>tmp; + wall_id.push_back(tmp); + } + mCells.push_back(new MeshCell(midx,midy,node_id,normvec,edge_id,wall_id,tc_id)); + tc_id++; + } + mCellGroups.push_back(new MeshCellGroup(groupname,mCells)); + } + } + _meshdata=new MeshData(nodes,edges,outedges,mCellGroups); + FixMeshEdges(); } -string MeshRouter::GetMeshFileName() const { +string MeshRouter::GetMeshFileName() const +{ - TiXmlDocument doc(_building->GetProjectFilename()); - if (!doc.LoadFile()){ - Log->Write("ERROR: \t%s", doc.ErrorDesc()); - Log->Write("ERROR: \t could not parse the project file"); - exit(EXIT_FAILURE); - } + TiXmlDocument doc(_building->GetProjectFilename()); + if (!doc.LoadFile()) { + Log->Write("ERROR: \t%s", doc.ErrorDesc()); + Log->Write("ERROR: \t could not parse the project file"); + exit(EXIT_FAILURE); + } - // everything is fine. proceed with parsing - TiXmlElement* xMainNode = doc.RootElement(); - TiXmlNode* xRouters=xMainNode->FirstChild("route_choice_models"); + // everything is fine. proceed with parsing + TiXmlElement* xMainNode = doc.RootElement(); + TiXmlNode* xRouters=xMainNode->FirstChild("route_choice_models"); - string mesh_file=""; + string mesh_file=""; - for(TiXmlElement* e = xRouters->FirstChildElement("router"); e; - e = e->NextSiblingElement("router")) { + for(TiXmlElement* e = xRouters->FirstChildElement("router"); e; + e = e->NextSiblingElement("router")) { - string strategy=e->Attribute("description"); + string strategy=e->Attribute("description"); - if(strategy=="nav_mesh"){ - if (e->FirstChild("parameters")->FirstChildElement("mesh_file")) - mesh_file=e->FirstChild("parameters")->FirstChildElement("mesh_file")->Attribute("file"); - } + if(strategy=="nav_mesh") { + if (e->FirstChild("parameters")->FirstChildElement("mesh_file")) + mesh_file=e->FirstChild("parameters")->FirstChildElement("mesh_file")->Attribute("file"); + } - } - return _building->GetProjectRootDir()+mesh_file; + } + return _building->GetProjectRootDir()+mesh_file; } diff --git a/routing/MeshRouter.h b/routing/MeshRouter.h index 76391ffcbe7d492f612c133b1a07cbbc66975598..f9907c2e0afabe98df28e4d7450cb820a7f031f5 100644 --- a/routing/MeshRouter.h +++ b/routing/MeshRouter.h @@ -12,22 +12,22 @@ #include "mesh/Mesh.h" class MeshRouter: public Router { - private: - Building* _building; - MeshData* _meshdata; +private: + Building* _building; + MeshData* _meshdata; - std::vector<MeshEdge*> AStar(Pedestrian* p,int& status)const; - NavLine Funnel(Point&,Point&,std::vector<MeshEdge*>)const; - NavLine FunnelRad(Point&,Point&,std::vector<MeshEdge*>); - MeshEdge* Visibility(Point&,Point&,std::vector<MeshEdge*>)const; - std::string GetMeshFileName() const; - void FixMeshEdges(); - public: - MeshRouter(); - virtual ~MeshRouter(); + std::vector<MeshEdge*> AStar(Pedestrian* p,int& status)const; + NavLine Funnel(Point&,Point&,std::vector<MeshEdge*>)const; + NavLine FunnelRad(Point&,Point&,std::vector<MeshEdge*>); + MeshEdge* Visibility(Point&,Point&,std::vector<MeshEdge*>)const; + std::string GetMeshFileName() const; + void FixMeshEdges(); +public: + MeshRouter(); + virtual ~MeshRouter(); - virtual int FindExit(Pedestrian* p); - virtual void Init(Building* b); + virtual int FindExit(Pedestrian* p); + virtual void Init(Building* b); }; diff --git a/routing/NavMesh.cpp b/routing/NavMesh.cpp index e1c0082e88e3d125bbf8c1d1c29995b50baaf821..2b4fae4521b1daf92eb8e23004a3a99e17d06e0e 100644 --- a/routing/NavMesh.cpp +++ b/routing/NavMesh.cpp @@ -21,2246 +21,2262 @@ using namespace std; -NavMesh::NavMesh(Building* b) { - _building=b; +NavMesh::NavMesh(Building* b) +{ + _building=b; } -NavMesh::~NavMesh() { +NavMesh::~NavMesh() +{ - for (unsigned int i = 0; i < _vertices.size(); i++) - delete _vertices[i]; + for (unsigned int i = 0; i < _vertices.size(); i++) + delete _vertices[i]; - for (unsigned int i = 0; i < _edges.size(); i++) - delete _edges[i]; + for (unsigned int i = 0; i < _edges.size(); i++) + delete _edges[i]; - for (unsigned int i = 0; i < _obst.size(); i++) - delete _obst[i]; + for (unsigned int i = 0; i < _obst.size(); i++) + delete _obst[i]; - for (unsigned int i = 0; i < _nodes.size(); i++) - delete _nodes[i]; + for (unsigned int i = 0; i < _nodes.size(); i++) + delete _nodes[i]; } -void NavMesh::BuildNavMesh() { +void NavMesh::BuildNavMesh() +{ - //compute the equations of the plane first. - ComputePlanesEquation(); + //compute the equations of the plane first. + ComputePlanesEquation(); - std::map<int,int> subroom_to_node; - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* r = _building->GetRoom(i); - string caption = r->GetCaption(); - - //skip the virtual room containing the complete geometry - //if(r->GetCaption()=="outside") continue; - - for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { - SubRoom* s = r->GetSubRoom(k); - - //vertices - const vector<Point>& pol = s->GetPolygon(); - - // Vertices - for (unsigned int p = 0; p < pol.size(); p++) { - JVertex* v = new JVertex(); - v->pPos= pol[p]; - if(AddVertex(v)==-1) { - delete v; - } - } - - //Nodes vertices - JNode* node = new JNode(); - node->pGroup = r->GetCaption(); - node->pCentroid = s->GetCentroid(); - //setting the node equation. important for real 3D informations - const double* ABC = s->GetPlanEquation(); - node->pNormalVec[0]=ABC[0]; - node->pNormalVec[1]=ABC[1]; - node->pNormalVec[2]=ABC[2]; - // ComputePlaneEquation(s,node->pNormalVec); - - for (unsigned int p = 0; p < pol.size(); p++) { - node->pHull.push_back(*(GetVertex(pol[p]))); - } - - - //edges are transitions and crossings - const vector<Crossing*>& crossings = s->GetAllCrossings(); - for (unsigned c = 0; c < crossings.size(); c++) { - - JEdge* e= new JEdge(); - int node0 = crossings[c]->GetSubRoom1()->GetUID(); - int node1 = crossings[c]->GetSubRoom2()->GetUID(); - Point P0 = crossings[c]->GetPoint1(); - Point P1 = crossings[c]->GetPoint2(); - - assert(node0!=node1); - e->pNode0=node0; - e->pNode1=node1; - e->pEnd=*GetVertex(P1); - e->pStart= *GetVertex(P0); - - - if (AddEdge(e)==-1) { - // the JEdge is already there - e->id=IsPortal(e->pStart.pPos, e->pEnd.pPos); - } - // caution: the ID is automatically assigned in the AddEdge method - node->pPortals.push_back(e->id); - } - - - const vector<Transition*>& transitions = s->GetAllTransitions(); - for (unsigned t = 0; t < transitions.size(); t++) { - - int node0 = transitions[t]->GetSubRoom1()->GetUID(); - int node1 = - (transitions[t]->GetSubRoom2() == NULL) ? - -1 : transitions[t]->GetSubRoom2()->GetUID(); - - Point centroid0 = transitions[t]->GetSubRoom1()->GetCentroid(); - - - if(transitions[t]->IsOpen()==true ) { // we are having an egde - // if(node1!=-1){ - - JEdge* e= new JEdge(); - - e->pNode0=node0; - e->pNode1=node1; - assert(node0!=node1); - - //first attempt - Point P0 = transitions[t]->GetPoint1(); - Point P1 = transitions[t]->GetPoint2(); - e->pEnd=*GetVertex(P1); - e->pStart= *GetVertex(P0); - - //TODO: release e memory - if (AddEdge(e)==-1) { - // the JEdge is already there - e->id=IsPortal(e->pStart.pPos, e->pEnd.pPos); - } - // caution: the ID is automatically assigned in the AddEdge method - node->pPortals.push_back(e->id); - - if(e->id==1766){ - DumpEdge(111); - cout<<"name: " <<transitions[t]->GetCaption()<<endl; - cout<<"room 1: " <<transitions[t]->GetRoom1()->GetCaption()<<endl; - cout<<"room2: " <<transitions[t]->GetRoom2()->GetCaption()<<endl; - assert(0); - } - } - else - { // we are having an JObstacle - JObstacle* o= new JObstacle(); - o->pNode0=node0; - o->pNextObst=-1; - - //first attempt - Point P0 = transitions[t]->GetPoint1(); - Point P1 = transitions[t]->GetPoint2(); - Point D0 = P1 - P0; - Point D1 = centroid0-P0; - if (D0.Det(D1) < 0) { - //o->pDisp=D0; - o->pEnd=*GetVertex(P1); - o->pStart= *GetVertex(P0); - - }else{ - o->pStart= *GetVertex(P1); - //o->pDisp=Point(0,0)-D0; - o->pEnd=*GetVertex(P0); - } - - if (AddObst(o)==-1) { - // the JObstacle is already there - o->id=IsObstacle(o->pStart.pPos, o->pEnd.pPos); - } - node->pObstacles.push_back(o->id); - } - - } - - //determine the group based on the crossings - if(crossings.size()==1 && transitions.size()==0){ - //JNode->pGroup="seat"; - node->pGroup=r->GetCaption(); - }else { - if(crossings.size()==2){ - if(crossings[0]->Length()==crossings[1]->Length()) - node->pGroup="seats"; - } - } - - //obstacles - const vector<Wall>& walls = s->GetAllWalls(); - for (unsigned w = 0; w < walls.size(); w++) { - - const Point& centroid0 = s->GetCentroid(); - int node0 = s->GetUID(); - - JObstacle* o= new JObstacle(); - o->pNode0=node0; - o->pNextObst=-1; - - //first attempt - Point P0 = walls[w].GetPoint1(); - Point P1 = walls[w].GetPoint2(); - Point D0 = P1 - P0; - Point D1 = centroid0-P0; - if (D0.Det(D1) < 0) { - //o->pDisp=D0; - o->pEnd=*GetVertex(P1); - o->pStart= *GetVertex(P0); - - }else{ - o->pStart= *GetVertex(P1); - //o->pDisp=Point(0,0)-D0; - o->pEnd=*GetVertex(P0); - } - - if (AddObst(o)==-1) { - // the JEdge is already there - o->id=IsObstacle(o->pStart.pPos, o->pEnd.pPos); - } - node->pObstacles.push_back(o->id); - } - - subroom_to_node[s->GetUID()]=node->id; - - if(r->GetCaption()!="outside") { - AddNode(node); - map_node_to_subroom[node->id]=make_pair(r->GetID(),s->GetSubRoomID()); - } - else { - delete node; - } - } - } - - // convexify the mesh - Convexify(); - //Triangulate(pNodes[pBuilding->GetRoom("030")->GetSubRoom(0)->GetUID()]); - //Triangulate(pNodes[pBuilding->GetRoom("040a")->GetSubRoom(0)->GetUID()]); - //Triangulate(pNodes[pBuilding->GetRoom("030a")->GetSubRoom(0)->GetUID()]); - //Finalize(); - FinalizeAlphaShape(); - //WriteToFileTraVisTo("promenade.nav.xml", pNodes[364]); exit(0); - //WriteToFileTraVisTo("promenade.nav.xml"); - //cout<<"groupe:"<<pNodes[365]->pGroup<<endl; - //cout<<"obst:"<<pNodes[1409]->pObstacles.size()<<endl; - //DumpObstacle(pNodes[1409]->pObstacles[0]); - //DumpNode(2341); - //DumpEdge(9); - UpdateNodes(); - Test(); - - std::sort(_nodes.begin(), _nodes.end(),JNode()); - - // doing the mapping - for(unsigned int i=0;i<_nodes.size();i++){ - subroom_to_node[_nodes[i]->id]=i; - _nodes[i]->id=i; - } - - - //normalizing the IDs - for (unsigned int e=0;e<_edges.size();e++){ - if(subroom_to_node.count(_edges[e]->pNode0)==0){ - cout<<"Node 0 id (edge): "<< _edges[e]->pNode0<<" not in the map"<<endl; - exit(0); - } - if(subroom_to_node.count(_edges[e]->pNode1)==0){ - cout<<"Node 1 id (edge): "<< _edges[e]->pNode1<<" not in the map"<<endl; - exit(0); - } - - _edges[e]->pNode0=subroom_to_node[_edges[e]->pNode0]; - _edges[e]->pNode1=subroom_to_node[_edges[e]->pNode1]; - } - - for (unsigned int ob=0;ob<_obst.size();ob++){ - if(subroom_to_node.count(_obst[ob]->pNode0)==0){ - cout<<"Node 0 id (obst): "<< _obst[ob]->pNode0<<" not in the map"<<endl; - exit(0); - } - _obst[ob]->pNode0=subroom_to_node[_obst[ob]->pNode0]; - } - - //chain the obstacles - for (unsigned int ob1 = 0; ob1 < _obst.size(); ob1++) - { continue; //FIXME - for (unsigned int ob2 = 0; ob2 < _obst.size(); ob2++) - { - JObstacle* obst1 = _obst[ob1]; - JObstacle* obst2 = _obst[ob2]; - - if (obst1->id == obst2->id) - continue; - int comVertex=obst1->GetCommonVertex(obst2); - if(comVertex==-1) - continue; - - if(obst1->pStart.id==comVertex) - { - obst2->pNextObst=obst1->id; - } - else - { - obst1->pNextObst=obst2->id; - } - - } - } - - Log->Write("INFO:\tMesh successfully generated!\n"); - // DumpNode(72); - // DumpEdge(66); - // exit(0); + std::map<int,int> subroom_to_node; + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* r = _building->GetRoom(i); + string caption = r->GetCaption(); + + //skip the virtual room containing the complete geometry + //if(r->GetCaption()=="outside") continue; + + for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { + SubRoom* s = r->GetSubRoom(k); + + //vertices + const vector<Point>& pol = s->GetPolygon(); + + // Vertices + for (unsigned int p = 0; p < pol.size(); p++) { + JVertex* v = new JVertex(); + v->pPos= pol[p]; + if(AddVertex(v)==-1) { + delete v; + } + } + + //Nodes vertices + JNode* node = new JNode(); + node->pGroup = r->GetCaption(); + node->pCentroid = s->GetCentroid(); + //setting the node equation. important for real 3D informations + const double* ABC = s->GetPlanEquation(); + node->pNormalVec[0]=ABC[0]; + node->pNormalVec[1]=ABC[1]; + node->pNormalVec[2]=ABC[2]; + // ComputePlaneEquation(s,node->pNormalVec); + + for (unsigned int p = 0; p < pol.size(); p++) { + node->pHull.push_back(*(GetVertex(pol[p]))); + } + + + //edges are transitions and crossings + const vector<Crossing*>& crossings = s->GetAllCrossings(); + for (unsigned c = 0; c < crossings.size(); c++) { + + JEdge* e= new JEdge(); + int node0 = crossings[c]->GetSubRoom1()->GetUID(); + int node1 = crossings[c]->GetSubRoom2()->GetUID(); + Point P0 = crossings[c]->GetPoint1(); + Point P1 = crossings[c]->GetPoint2(); + + assert(node0!=node1); + e->pNode0=node0; + e->pNode1=node1; + e->pEnd=*GetVertex(P1); + e->pStart= *GetVertex(P0); + + + if (AddEdge(e)==-1) { + // the JEdge is already there + e->id=IsPortal(e->pStart.pPos, e->pEnd.pPos); + } + // caution: the ID is automatically assigned in the AddEdge method + node->pPortals.push_back(e->id); + } + + + const vector<Transition*>& transitions = s->GetAllTransitions(); + for (unsigned t = 0; t < transitions.size(); t++) { + + int node0 = transitions[t]->GetSubRoom1()->GetUID(); + int node1 = + (transitions[t]->GetSubRoom2() == NULL) ? + -1 : transitions[t]->GetSubRoom2()->GetUID(); + + Point centroid0 = transitions[t]->GetSubRoom1()->GetCentroid(); + + + if(transitions[t]->IsOpen()==true ) { // we are having an egde + // if(node1!=-1){ + + JEdge* e= new JEdge(); + + e->pNode0=node0; + e->pNode1=node1; + assert(node0!=node1); + + //first attempt + Point P0 = transitions[t]->GetPoint1(); + Point P1 = transitions[t]->GetPoint2(); + e->pEnd=*GetVertex(P1); + e->pStart= *GetVertex(P0); + + //TODO: release e memory + if (AddEdge(e)==-1) { + // the JEdge is already there + e->id=IsPortal(e->pStart.pPos, e->pEnd.pPos); + } + // caution: the ID is automatically assigned in the AddEdge method + node->pPortals.push_back(e->id); + + if(e->id==1766) { + DumpEdge(111); + cout<<"name: " <<transitions[t]->GetCaption()<<endl; + cout<<"room 1: " <<transitions[t]->GetRoom1()->GetCaption()<<endl; + cout<<"room2: " <<transitions[t]->GetRoom2()->GetCaption()<<endl; + assert(0); + } + } else { + // we are having an JObstacle + JObstacle* o= new JObstacle(); + o->pNode0=node0; + o->pNextObst=-1; + + //first attempt + Point P0 = transitions[t]->GetPoint1(); + Point P1 = transitions[t]->GetPoint2(); + Point D0 = P1 - P0; + Point D1 = centroid0-P0; + if (D0.Det(D1) < 0) { + //o->pDisp=D0; + o->pEnd=*GetVertex(P1); + o->pStart= *GetVertex(P0); + + } else { + o->pStart= *GetVertex(P1); + //o->pDisp=Point(0,0)-D0; + o->pEnd=*GetVertex(P0); + } + + if (AddObst(o)==-1) { + // the JObstacle is already there + o->id=IsObstacle(o->pStart.pPos, o->pEnd.pPos); + } + node->pObstacles.push_back(o->id); + } + + } + + //determine the group based on the crossings + if(crossings.size()==1 && transitions.size()==0) { + //JNode->pGroup="seat"; + node->pGroup=r->GetCaption(); + } else { + if(crossings.size()==2) { + if(crossings[0]->Length()==crossings[1]->Length()) + node->pGroup="seats"; + } + } + + //obstacles + const vector<Wall>& walls = s->GetAllWalls(); + for (unsigned w = 0; w < walls.size(); w++) { + + const Point& centroid0 = s->GetCentroid(); + int node0 = s->GetUID(); + + JObstacle* o= new JObstacle(); + o->pNode0=node0; + o->pNextObst=-1; + + //first attempt + Point P0 = walls[w].GetPoint1(); + Point P1 = walls[w].GetPoint2(); + Point D0 = P1 - P0; + Point D1 = centroid0-P0; + if (D0.Det(D1) < 0) { + //o->pDisp=D0; + o->pEnd=*GetVertex(P1); + o->pStart= *GetVertex(P0); + + } else { + o->pStart= *GetVertex(P1); + //o->pDisp=Point(0,0)-D0; + o->pEnd=*GetVertex(P0); + } + + if (AddObst(o)==-1) { + // the JEdge is already there + o->id=IsObstacle(o->pStart.pPos, o->pEnd.pPos); + } + node->pObstacles.push_back(o->id); + } + + subroom_to_node[s->GetUID()]=node->id; + + if(r->GetCaption()!="outside") { + AddNode(node); + map_node_to_subroom[node->id]=make_pair(r->GetID(),s->GetSubRoomID()); + } else { + delete node; + } + } + } + + // convexify the mesh + Convexify(); + //Triangulate(pNodes[pBuilding->GetRoom("030")->GetSubRoom(0)->GetUID()]); + //Triangulate(pNodes[pBuilding->GetRoom("040a")->GetSubRoom(0)->GetUID()]); + //Triangulate(pNodes[pBuilding->GetRoom("030a")->GetSubRoom(0)->GetUID()]); + //Finalize(); + FinalizeAlphaShape(); + //WriteToFileTraVisTo("promenade.nav.xml", pNodes[364]); exit(0); + //WriteToFileTraVisTo("promenade.nav.xml"); + //cout<<"groupe:"<<pNodes[365]->pGroup<<endl; + //cout<<"obst:"<<pNodes[1409]->pObstacles.size()<<endl; + //DumpObstacle(pNodes[1409]->pObstacles[0]); + //DumpNode(2341); + //DumpEdge(9); + UpdateNodes(); + Test(); + + std::sort(_nodes.begin(), _nodes.end(),JNode()); + + // doing the mapping + for(unsigned int i=0; i<_nodes.size(); i++) { + subroom_to_node[_nodes[i]->id]=i; + _nodes[i]->id=i; + } + + + //normalizing the IDs + for (unsigned int e=0; e<_edges.size(); e++) { + if(subroom_to_node.count(_edges[e]->pNode0)==0) { + cout<<"Node 0 id (edge): "<< _edges[e]->pNode0<<" not in the map"<<endl; + exit(0); + } + if(subroom_to_node.count(_edges[e]->pNode1)==0) { + cout<<"Node 1 id (edge): "<< _edges[e]->pNode1<<" not in the map"<<endl; + exit(0); + } + + _edges[e]->pNode0=subroom_to_node[_edges[e]->pNode0]; + _edges[e]->pNode1=subroom_to_node[_edges[e]->pNode1]; + } + + for (unsigned int ob=0; ob<_obst.size(); ob++) { + if(subroom_to_node.count(_obst[ob]->pNode0)==0) { + cout<<"Node 0 id (obst): "<< _obst[ob]->pNode0<<" not in the map"<<endl; + exit(0); + } + _obst[ob]->pNode0=subroom_to_node[_obst[ob]->pNode0]; + } + + //chain the obstacles + for (unsigned int ob1 = 0; ob1 < _obst.size(); ob1++) { + continue; //FIXME + for (unsigned int ob2 = 0; ob2 < _obst.size(); ob2++) { + JObstacle* obst1 = _obst[ob1]; + JObstacle* obst2 = _obst[ob2]; + + if (obst1->id == obst2->id) + continue; + int comVertex=obst1->GetCommonVertex(obst2); + if(comVertex==-1) + continue; + + if(obst1->pStart.id==comVertex) { + obst2->pNextObst=obst1->id; + } else { + obst1->pNextObst=obst2->id; + } + + } + } + + Log->Write("INFO:\tMesh successfully generated!\n"); + // DumpNode(72); + // DumpEdge(66); + // exit(0); } -void NavMesh::DumpNode(int id) { - JNode *nd=_nodes[id]; +void NavMesh::DumpNode(int id) +{ + JNode *nd=_nodes[id]; - std::cerr<<endl<<"Node ID: "<<id<<endl; - std::cerr<<"Hull ID: [ "<<endl; - for(unsigned int i=0;i<nd->pHull.size();i++) - { - std::cerr<<nd->pHull[i].id<<" "; - } - std::cerr<<endl<<" ]"<<endl; + std::cerr<<endl<<"Node ID: "<<id<<endl; + std::cerr<<"Hull ID: [ "<<endl; + for(unsigned int i=0; i<nd->pHull.size(); i++) { + std::cerr<<nd->pHull[i].id<<" "; + } + std::cerr<<endl<<" ]"<<endl; - std::cerr<<"Obstacles ID: ["<<endl; - for( unsigned int i=0;i<nd->pObstacles.size();i++){ - std::cerr<<nd->pObstacles[i]<<" "; - } - std::cerr<<endl<<" ]"<<endl; + std::cerr<<"Obstacles ID: ["<<endl; + for( unsigned int i=0; i<nd->pObstacles.size(); i++) { + std::cerr<<nd->pObstacles[i]<<" "; + } + std::cerr<<endl<<" ]"<<endl; - std::cerr<<"Portals ID: ["<<endl; - for( unsigned int i=0;i<nd->pPortals.size();i++){ - std::cerr<<nd->pPortals[i]<<" "; - } - std::cerr<<endl<<" ]"<<endl<<endl; + std::cerr<<"Portals ID: ["<<endl; + for( unsigned int i=0; i<nd->pPortals.size(); i++) { + std::cerr<<nd->pPortals[i]<<" "; + } + std::cerr<<endl<<" ]"<<endl<<endl; } -void NavMesh::DumpEdge(int id){ - JEdge* e= _edges[id]; - std::cerr<<endl<<"Edge: "<<endl; - std::cerr<<"id: "<<e->id<<endl; - std::cerr<<"node 0: "<<e->pNode0<<endl; - std::cerr<<"node 1: "<<e->pNode1<<endl<<endl; +void NavMesh::DumpEdge(int id) +{ + JEdge* e= _edges[id]; + std::cerr<<endl<<"Edge: "<<endl; + std::cerr<<"id: "<<e->id<<endl; + std::cerr<<"node 0: "<<e->pNode0<<endl; + std::cerr<<"node 1: "<<e->pNode1<<endl<<endl; } -void NavMesh::DumpObstacle(int id){ - JObstacle* o= _obst[id]; - std::cerr<<endl<<"Obstacle: "<<endl; - std::cerr<<"id: "<<o->id<<endl; - std::cerr<<"node 0: "<<o->pNode0<<endl<<endl; +void NavMesh::DumpObstacle(int id) +{ + JObstacle* o= _obst[id]; + std::cerr<<endl<<"Obstacle: "<<endl; + std::cerr<<"id: "<<o->id<<endl; + std::cerr<<"node 0: "<<o->pNode0<<endl<<endl; } -void NavMesh::Convexify() { - - Log->Write("INFO:\tGenerating the navigation mesh!"); - for (unsigned int n = 0; n < _nodes.size(); n++) { - - JNode* old_node = _nodes[n]; - if (old_node->IsClockwise()) { - reverse(old_node->pHull.begin(), old_node->pHull.end()); - } - - if (old_node->IsConvex() == false) { +void NavMesh::Convexify() +{ - Triangulate(old_node); - } - } - Log->Write("INFO:\t...Done!"); + Log->Write("INFO:\tGenerating the navigation mesh!"); + for (unsigned int n = 0; n < _nodes.size(); n++) { - /* - //will hold the newly created elements - std::vector<JVertex*> new_vertices; - std::vector<JEdge*> new_edges; - std::vector<JObstacle*> new_obsts; + JNode* old_node = _nodes[n]; + if (old_node->IsClockwise()) { + reverse(old_node->pHull.begin(), old_node->pHull.end()); + } - std::vector<JNode*> nodes_to_be_deleted; + if (old_node->IsConvex() == false) { - for (unsigned int n = 0; n < pNodes.size(); n++) { - - JNode* old_node = pNodes[n]; - if (old_node->IsClockwise()) { - reverse(old_node->pHull.begin(), old_node->pHull.end()); - } - - if (old_node->IsConvex() == false) { - -#ifdef _CGAL - string group=old_node->pGroup; - -#ifdef _DEBUG - cout<<"convexifing:" <<group<< " ID: "<<old_node->id <<endl; -#endif -// const char* myGroups[] = {"030"}; -// vector<string> nodes_to_plot (myGroups, myGroups + sizeof(myGroups) / sizeof(char*) ); -// -// if (IsElementInVector(nodes_to_plot, group) == false) -// continue; + Triangulate(old_node); + } + } + Log->Write("INFO:\t...Done!"); - //schedule this JNode for deletion - nodes_to_be_deleted.push_back(old_node); + /* + //will hold the newly created elements + std::vector<JVertex*> new_vertices; + std::vector<JEdge*> new_edges; + std::vector<JObstacle*> new_obsts; - Polygon_2 polygon; - Polygon_list partition_polys; - Traits partition_traits; - Validity_traits validity_traits; + std::vector<JNode*> nodes_to_be_deleted; - //create the CGAL structure - for(unsigned int i=0;i<old_node->pHull.size();i++){ - double x=pVertices[old_node->pHull[i].id]->pPos.GetX() ; - double y=pVertices[old_node->pHull[i].id]->pPos.GetY() ; - polygon.push_back(Point_2(x, y)); + for (unsigned int n = 0; n < pNodes.size(); n++) { - } + JNode* old_node = pNodes[n]; + if (old_node->IsClockwise()) { + reverse(old_node->pHull.begin(), old_node->pHull.end()); + } + if (old_node->IsConvex() == false) { - //polygon - try { - if(polygon.is_clockwise_oriented()) polygon.reverse_orientation(); + #ifdef _CGAL + string group=old_node->pGroup; - //create the partitions - CGAL::optimal_convex_partition_2(polygon.vertices_begin(), - //CGAL::approx_convex_partition_2(polygon.vertices_begin(), - polygon.vertices_end(), std::back_inserter(partition_polys), - partition_traits); + #ifdef _DEBUG + cout<<"convexifing:" <<group<< " ID: "<<old_node->id <<endl; + #endif + // const char* myGroups[] = {"030"}; + // vector<string> nodes_to_plot (myGroups, myGroups + sizeof(myGroups) / sizeof(char*) ); + // + // if (IsElementInVector(nodes_to_plot, group) == false) + // continue; - //check the created partitions - assert(CGAL::partition_is_valid_2(polygon.vertices_begin(), - polygon.vertices_end(), partition_polys.begin(), - partition_polys.end(), validity_traits)); + //schedule this JNode for deletion + nodes_to_be_deleted.push_back(old_node); + Polygon_2 polygon; + Polygon_list partition_polys; + Traits partition_traits; + Validity_traits validity_traits; - } - catch(const exception & e) { + //create the CGAL structure + for(unsigned int i=0;i<old_node->pHull.size();i++){ + double x=pVertices[old_node->pHull[i].id]->pPos.GetX() ; + double y=pVertices[old_node->pHull[i].id]->pPos.GetY() ; + polygon.push_back(Point_2(x, y)); - cout<<"node :" <<old_node->id <<" could not be converted" <<endl; - cout<<" in Group: " <<old_node->pGroup <<endl; - cout<<" Portals: " <<old_node->pPortals.size() <<endl; - cout<<" Obstacles: " <<old_node->pObstacles.size() <<endl; - problem_nodes.push_back(old_node->id); - cout<<e.what()<<endl; - //Triangulate(old_node); - //exit(EXIT_FAILURE); - //return; - //continue; - } + } - //make the changes to the nav mesh - for (Polygon_iterator pit = partition_polys.begin(); - pit != partition_polys.end(); ++pit) { + //polygon + try { + if(polygon.is_clockwise_oriented()) polygon.reverse_orientation(); - JNode* new_node = new JNode(); - new_node->pGroup = old_node->pGroup; - //to get a correct ID - AddNode(new_node); - new_nodes.push_back(new_node); + //create the partitions + CGAL::optimal_convex_partition_2(polygon.vertices_begin(), + //CGAL::approx_convex_partition_2(polygon.vertices_begin(), + polygon.vertices_end(), std::back_inserter(partition_polys), + partition_traits); - Point_2 c2 =CGAL::centroid(pit->vertices_begin(),pit->vertices_end(),CGAL::Dimension_tag<0>()); + //check the created partitions + assert(CGAL::partition_is_valid_2(polygon.vertices_begin(), + polygon.vertices_end(), partition_polys.begin(), + partition_polys.end(), validity_traits)); - new_node->pCentroid= Point(c2.x(),c2.y()); - new_node->pNormalVec[0]=old_node->pNormalVec[0]; - new_node->pNormalVec[1]=old_node->pNormalVec[1]; - new_node->pNormalVec[2]=old_node->pNormalVec[2]; + } + catch(const exception & e) { - for (Vertex_iterator vit = pit->vertices_begin(); - vit != pit->vertices_end(); ++vit) { - new_node->pHull.push_back(*(GetVertex(Point(vit->x(), vit->y())))); - } + cout<<"node :" <<old_node->id <<" could not be converted" <<endl; + cout<<" in Group: " <<old_node->pGroup <<endl; + cout<<" Portals: " <<old_node->pPortals.size() <<endl; + cout<<" Obstacles: " <<old_node->pObstacles.size() <<endl; + problem_nodes.push_back(old_node->id); + cout<<e.what()<<endl; + //Triangulate(old_node); + //exit(EXIT_FAILURE); + //return; + //continue; + } + //make the changes to the nav mesh + for (Polygon_iterator pit = partition_polys.begin(); + pit != partition_polys.end(); ++pit) { - if(new_node->IsClockwise()){ - std::reverse(new_node->pHull.begin(), new_node->pHull.end()); - } - for (Edge_iterator eit=pit->edges_begin();eit!=pit->edges_end();++eit){ + JNode* new_node = new JNode(); + new_node->pGroup = old_node->pGroup; + //to get a correct ID + AddNode(new_node); + new_nodes.push_back(new_node); - Point P0 = Point (eit->start().x(), eit->start().y()); - Point P1 = Point (eit->end().x(), eit->end().y()); + Point_2 c2 =CGAL::centroid(pit->vertices_begin(),pit->vertices_end(),CGAL::Dimension_tag<0>()); + new_node->pCentroid= Point(c2.x(),c2.y()); - int edge_id=IsPortal(P0,P1); - if(edge_id != -1){ - new_node->pPortals.push_back(edge_id); - JEdge* e = pEdges[edge_id]; + new_node->pNormalVec[0]=old_node->pNormalVec[0]; + new_node->pNormalVec[1]=old_node->pNormalVec[1]; + new_node->pNormalVec[2]=old_node->pNormalVec[2]; + + for (Vertex_iterator vit = pit->vertices_begin(); + vit != pit->vertices_end(); ++vit) { + new_node->pHull.push_back(*(GetVertex(Point(vit->x(), vit->y())))); + } + + + if(new_node->IsClockwise()){ + std::reverse(new_node->pHull.begin(), new_node->pHull.end()); + } + + for (Edge_iterator eit=pit->edges_begin();eit!=pit->edges_end();++eit){ + + Point P0 = Point (eit->start().x(), eit->start().y()); + Point P1 = Point (eit->end().x(), eit->end().y()); + + + int edge_id=IsPortal(P0,P1); + if(edge_id != -1){ + new_node->pPortals.push_back(edge_id); + JEdge* e = pEdges[edge_id]; + + //invalidate the node + e->pNode0=-1; + e->pNode1=-1; + } + + int obstacle_id=IsObstacle(P0,P1); + if(obstacle_id != -1){ + //std::cerr<<"Error: the convexification has created an JObstacle"<<endl; + new_node->pObstacles.push_back(obstacle_id); + pObst[obstacle_id]->pNode0=-1; + } - //invalidate the node - e->pNode0=-1; - e->pNode1=-1; - } + // this portal was newly created + if ((obstacle_id==-1) && (edge_id==-1)){ - int obstacle_id=IsObstacle(P0,P1); - if(obstacle_id != -1){ - //std::cerr<<"Error: the convexification has created an JObstacle"<<endl; - new_node->pObstacles.push_back(obstacle_id); - pObst[obstacle_id]->pNode0=-1; - } + JEdge* e= new JEdge(); + e->pEnd=*GetVertex(P1); + e->pStart= *GetVertex(P0); + AddEdge(e); - // this portal was newly created - if ((obstacle_id==-1) && (edge_id==-1)){ + //invalidate the node + e->pNode0=-1; + e->pNode1=-1; - JEdge* e= new JEdge(); - e->pEnd=*GetVertex(P1); - e->pStart= *GetVertex(P0); - AddEdge(e); + // caution: the ID is automatically assigned in the AddEdge method + new_node->pPortals.push_back(e->id); + } + } + } + #endif + } + } - //invalidate the node - e->pNode0=-1; - e->pNode1=-1; + #ifdef _DEBUG + cout <<"before: " <<endl; + cout << pNodes.size() <<" total nodes" <<endl; + cout << new_nodes.size() <<" new nodes were created" <<endl; + cout<< nodes_to_be_deleted.size()<<" nodes to be deleted"<<endl; + #endif - // caution: the ID is automatically assigned in the AddEdge method - new_node->pPortals.push_back(e->id); - } - } - } -#endif - } - } + UpdateEdges(); + UpdateObstacles(); -#ifdef _DEBUG - cout <<"before: " <<endl; - cout << pNodes.size() <<" total nodes" <<endl; - cout << new_nodes.size() <<" new nodes were created" <<endl; - cout<< nodes_to_be_deleted.size()<<" nodes to be deleted"<<endl; -#endif - UpdateEdges(); - UpdateObstacles(); + // now post processing the newly created nodes + for (unsigned int i=0;i<nodes_to_be_deleted.size();i++){ + JNode* node_to_delete = nodes_to_be_deleted[i]; + JNode* new_node = pNodes.back(); + pNodes.pop_back(); + + assert (node_to_delete->id != new_node->id && "Trying to remove the last node !"); - // now post processing the newly created nodes - for (unsigned int i=0;i<nodes_to_be_deleted.size();i++){ - JNode* node_to_delete = nodes_to_be_deleted[i]; + //making the transformation - JNode* new_node = pNodes.back(); - pNodes.pop_back(); + for(unsigned int i=0;i<new_node->pObstacles.size();i++){ + pObst[new_node->pObstacles[i]]->pNode0=node_to_delete->id; + } - assert (node_to_delete->id != new_node->id && "Trying to remove the last node !"); - //making the transformation + for(unsigned int i=0;i<new_node->pPortals.size();i++){ + JEdge* e= pEdges[new_node->pPortals[i]]; - for(unsigned int i=0;i<new_node->pObstacles.size();i++){ - pObst[new_node->pObstacles[i]]->pNode0=node_to_delete->id; - } + // if(e->pNode0==node_to_delete->id || e->pNode1==node_to_delete->id){ + // + // }else{ + // + // + // if(e->pNode0==new_node->id){ + // e->pNode0=node_to_delete->id; + // } + // else if(e->pNode1==new_node->id) + // //else + // { + // e->pNode1=node_to_delete->id; + // } + // } + if(pEdges[new_node->pPortals[i]]->pNode0==new_node->id){ + pEdges[new_node->pPortals[i]]->pNode0=node_to_delete->id; + } + // else if(pEdges[new_node->pPortals[i]]->pNode1==new_node->id) + else + { + pEdges[new_node->pPortals[i]]->pNode1=node_to_delete->id; + } + } - for(unsigned int i=0;i<new_node->pPortals.size();i++){ - JEdge* e= pEdges[new_node->pPortals[i]]; + new_node->id=node_to_delete->id; + pNodes[node_to_delete->id]=new_node; + + #ifdef _DEBUG + cout<<"deleting node: "<<node_to_delete->id<<endl; + #endif + delete node_to_delete; + } + + #ifdef _DEBUG + cout <<"after: " <<endl; + cout << pNodes.size() <<" total nodes" <<endl; + cout << new_nodes.size() <<" new nodes were created" <<endl; + cout<< nodes_to_be_deleted.size()<<" nodes to be deleted"<<endl; + #endif + + + //final cleaning + + UpdateEdges(); + UpdateObstacles(); + + //exit(0); -// if(e->pNode0==node_to_delete->id || e->pNode1==node_to_delete->id){ -// -// }else{ -// -// -// if(e->pNode0==new_node->id){ -// e->pNode0=node_to_delete->id; -// } -// else if(e->pNode1==new_node->id) -// //else -// { -// e->pNode1=node_to_delete->id; -// } -// } - - if(pEdges[new_node->pPortals[i]]->pNode0==new_node->id){ - pEdges[new_node->pPortals[i]]->pNode0=node_to_delete->id; - } -// else if(pEdges[new_node->pPortals[i]]->pNode1==new_node->id) - else - { - pEdges[new_node->pPortals[i]]->pNode1=node_to_delete->id; - } - } - - new_node->id=node_to_delete->id; - pNodes[node_to_delete->id]=new_node; - -#ifdef _DEBUG - cout<<"deleting node: "<<node_to_delete->id<<endl; -#endif - delete node_to_delete; - } - -#ifdef _DEBUG - cout <<"after: " <<endl; - cout << pNodes.size() <<" total nodes" <<endl; - cout << new_nodes.size() <<" new nodes were created" <<endl; - cout<< nodes_to_be_deleted.size()<<" nodes to be deleted"<<endl; -#endif - - - //final cleaning - - UpdateEdges(); - UpdateObstacles(); - - //exit(0); - - - */ + + */ } -void NavMesh::WriteToString(std::string& output) { - - std::stringstream file; - file.precision(2); - file<<fixed; - - //Point centre (10299,2051); - Point centre (0,0); - double factor=100; - - //writing the nodes - // int mynodes[] = {47, 30 ,38}; - // int mynodes[] = {41, 1521}; - int mynodes[] = {}; - //int mynodes[] = { 28, 27, 40}; - vector<int> nodes_to_plot (mynodes, mynodes + sizeof(mynodes) / sizeof(int) ); - - - //for (unsigned int n=0;n<new_nodes.size();n++){ - // JNode* JNode=new_nodes[n]; - - for (unsigned int n=0;n<_nodes.size();n++){ - JNode* node=_nodes[n]; - - int node_id=node->id; //cout<<"node id: "<<node_id<<endl; - if(nodes_to_plot.size()!=0) - if (IsElementInVector(nodes_to_plot, node_id) == false) - continue; - // if(problem_nodes.size()!=0) - // if (IsElementInVector(problem_nodes, node_id) == false) - // continue; - - //if(node->pGroup!="080") continue; - // if(node->pPortals.size()<10) continue; - //if(node->IsConvex()==true) continue; - //if(node->IsClockwise()==true) continue; - - file<<"\t\t<label centerX=\""<<node->pCentroid.GetX()*factor -centre.GetX()<<"\" centerY=\""<<node->pCentroid.GetY()*factor-centre.GetY()<<"\" centerZ=\"0\" text=\""<<node->id <<"\" color=\"100\" />"<<endl; - // cout<<"size: "<< node->pHull.size()<<endl; - // std::sort(node->pHull.begin(), node->pHull.end()); - // node->pHull.erase(std::unique(node->pHull.begin(), node->pHull.end()), node->pHull.end()); - // cout<<"size: "<< node->pHull.size()<<endl; - - for(unsigned int i=0;i<node->pHull.size();i++){ - //double x=pVertices[JNode->pHull[i].id]->pPos.GetX()*factor -centre.pX; - //double y=pVertices[JNode->pHull[i].id]->pPos.GetY()*factor -centre.pY; - //file<<" \t\t<sphere centerX=\""<<x<<"\" centerY=\""<<y<<"\" centerZ=\"0\" radius=\"5\" color=\"100\" />"<<endl; - //file<<"\t\t<label centerX=\""<<x<<"\" centerY=\""<<y<<"\" centerZ=\"0\" text=\""<<JNode->pHull[i].id<<"\" color=\"20\" />"<<endl; - - // draw the convex hull - // unsigned int size= node->pHull.size(); - // file<<" \t\t<sphere centerX=\""<<x<<"\" centerY=\""<<y<<"\" centerZ=\"0\" radius=\"5\" color=\"100\" />"<<endl; - // file<<"\t\t<label centerX=\""<<x<<"\" centerY=\""<<y<<"\" centerZ=\"0\" text=\""<<i<<"\" color=\"20\" />"<<endl; - // double x1=pVertices[node->pHull[i%size].id]->pPos.GetX()*factor -centre.pX; - // double y1=pVertices[node->pHull[i%size].id]->pPos.GetY()*factor -centre.pY; - // double x2=pVertices[node->pHull[(i+1)%size].id]->pPos.GetX()*factor -centre.pX; - // double y2=pVertices[node->pHull[(i+1)%size].id]->pPos.GetY()*factor -centre.pY; - // file<<"\t\t<wall id = \""<<i<<"\">"<<endl; - // file<<"\t\t\t<point xPos=\""<<x1<<"\" yPos=\""<<y1<<"\"/>"<<endl; - // file<<"\t\t\t<point xPos=\""<<x2<<"\" yPos=\""<<y2<<"\"/>"<<endl; - // file<<"\t\t</wall>"<<endl; - // cout.precision(2); - // cout<<fixed; - // printf("polygon.push_back(Point_2(%f, %f));\n",x1,y1); - } - file<<endl; - - for(unsigned int i=0;i<_obst.size();i++){ - JObstacle* obst=_obst[i]; - - if(obst->pNode0==node_id ){ - double x1=obst->pStart.pPos.GetX()*factor-centre._x; - double y1=obst->pStart.pPos.GetY()*factor-centre._y; - double x2=obst->pEnd.pPos.GetX()*factor-centre._x; - double y2=obst->pEnd.pPos.GetY()*factor-centre._y; - - //file<<"\t\t<label centerX=\""<<0.5*(x1+x2)<<"\" centerY=\""<<0.5*(y1+y2)<<"\" centerZ=\"0\" text=\""<<obst->id<<"\" color=\"20\" />"<<endl; - file<<"\t\t<wall id = \""<<i<<"\">"<<endl; - file<<"\t\t\t<point xPos=\""<<x1<<"\" yPos=\""<<y1<<"\"/>"<<endl; - file<<"\t\t\t<point xPos=\""<<x2<<"\" yPos=\""<<y2<<"\"/>"<<endl; - file<<"\t\t</wall>"<<endl; - } - - } - file<<endl; - - for(unsigned int i=0;i<_edges.size();i++){ - JEdge* edge=_edges[i]; - - if(edge->pNode0==node_id || edge->pNode1==node_id){ - double x1=edge->pStart.pPos.GetX()*factor-centre._x; - double y1=edge->pStart.pPos.GetY()*factor-centre._y; - double x2=edge->pEnd.pPos.GetX()*factor-centre._x; - double y2=edge->pEnd.pPos.GetY()*factor-centre._y; - - file<<"\t\t<label centerX=\""<<0.5*(x1+x2)<<"\" centerY=\""<<0.5*(y1+y2)<<"\" centerZ=\"0\" text=\""<<edge->id<<"\" color=\"20\" />"<<endl; - file<<"\t\t<door id = \""<<i<<"\">"<<endl; - file<<"\t\t\t<point xPos=\""<<x1<<"\" yPos=\""<<y1<<"\"/>"<<endl; - file<<"\t\t\t<point xPos=\""<<x2<<"\" yPos=\""<<y2<<"\"/>"<<endl; - file<<"\t\t</door>"<<endl; - } - } - - file<<endl; - } - - //eventually write any goal - for (map<int, Goal*>::const_iterator itr = _building->GetAllGoals().begin(); - itr != _building->GetAllGoals().end(); ++itr) { - - //int door=itr->first; - Goal* goal = itr->second; - file<<goal->Write()<<endl; - } - output=file.str(); +void NavMesh::WriteToString(std::string& output) +{ + + std::stringstream file; + file.precision(2); + file<<fixed; + + //Point centre (10299,2051); + Point centre (0,0); + double factor=100; + + //writing the nodes + // int mynodes[] = {47, 30 ,38}; + // int mynodes[] = {41, 1521}; + int mynodes[] = {}; + //int mynodes[] = { 28, 27, 40}; + vector<int> nodes_to_plot (mynodes, mynodes + sizeof(mynodes) / sizeof(int) ); + + + //for (unsigned int n=0;n<new_nodes.size();n++){ + // JNode* JNode=new_nodes[n]; + + for (unsigned int n=0; n<_nodes.size(); n++) { + JNode* node=_nodes[n]; + + int node_id=node->id; //cout<<"node id: "<<node_id<<endl; + if(nodes_to_plot.size()!=0) + if (IsElementInVector(nodes_to_plot, node_id) == false) + continue; + // if(problem_nodes.size()!=0) + // if (IsElementInVector(problem_nodes, node_id) == false) + // continue; + + //if(node->pGroup!="080") continue; + // if(node->pPortals.size()<10) continue; + //if(node->IsConvex()==true) continue; + //if(node->IsClockwise()==true) continue; + + file<<"\t\t<label centerX=\""<<node->pCentroid.GetX()*factor -centre.GetX()<<"\" centerY=\""<<node->pCentroid.GetY()*factor-centre.GetY()<<"\" centerZ=\"0\" text=\""<<node->id <<"\" color=\"100\" />"<<endl; + // cout<<"size: "<< node->pHull.size()<<endl; + // std::sort(node->pHull.begin(), node->pHull.end()); + // node->pHull.erase(std::unique(node->pHull.begin(), node->pHull.end()), node->pHull.end()); + // cout<<"size: "<< node->pHull.size()<<endl; + + for(unsigned int i=0; i<node->pHull.size(); i++) { + //double x=pVertices[JNode->pHull[i].id]->pPos.GetX()*factor -centre.pX; + //double y=pVertices[JNode->pHull[i].id]->pPos.GetY()*factor -centre.pY; + //file<<" \t\t<sphere centerX=\""<<x<<"\" centerY=\""<<y<<"\" centerZ=\"0\" radius=\"5\" color=\"100\" />"<<endl; + //file<<"\t\t<label centerX=\""<<x<<"\" centerY=\""<<y<<"\" centerZ=\"0\" text=\""<<JNode->pHull[i].id<<"\" color=\"20\" />"<<endl; + + // draw the convex hull + // unsigned int size= node->pHull.size(); + // file<<" \t\t<sphere centerX=\""<<x<<"\" centerY=\""<<y<<"\" centerZ=\"0\" radius=\"5\" color=\"100\" />"<<endl; + // file<<"\t\t<label centerX=\""<<x<<"\" centerY=\""<<y<<"\" centerZ=\"0\" text=\""<<i<<"\" color=\"20\" />"<<endl; + // double x1=pVertices[node->pHull[i%size].id]->pPos.GetX()*factor -centre.pX; + // double y1=pVertices[node->pHull[i%size].id]->pPos.GetY()*factor -centre.pY; + // double x2=pVertices[node->pHull[(i+1)%size].id]->pPos.GetX()*factor -centre.pX; + // double y2=pVertices[node->pHull[(i+1)%size].id]->pPos.GetY()*factor -centre.pY; + // file<<"\t\t<wall id = \""<<i<<"\">"<<endl; + // file<<"\t\t\t<point xPos=\""<<x1<<"\" yPos=\""<<y1<<"\"/>"<<endl; + // file<<"\t\t\t<point xPos=\""<<x2<<"\" yPos=\""<<y2<<"\"/>"<<endl; + // file<<"\t\t</wall>"<<endl; + // cout.precision(2); + // cout<<fixed; + // printf("polygon.push_back(Point_2(%f, %f));\n",x1,y1); + } + file<<endl; + + for(unsigned int i=0; i<_obst.size(); i++) { + JObstacle* obst=_obst[i]; + + if(obst->pNode0==node_id ) { + double x1=obst->pStart.pPos.GetX()*factor-centre._x; + double y1=obst->pStart.pPos.GetY()*factor-centre._y; + double x2=obst->pEnd.pPos.GetX()*factor-centre._x; + double y2=obst->pEnd.pPos.GetY()*factor-centre._y; + + //file<<"\t\t<label centerX=\""<<0.5*(x1+x2)<<"\" centerY=\""<<0.5*(y1+y2)<<"\" centerZ=\"0\" text=\""<<obst->id<<"\" color=\"20\" />"<<endl; + file<<"\t\t<wall id = \""<<i<<"\">"<<endl; + file<<"\t\t\t<point xPos=\""<<x1<<"\" yPos=\""<<y1<<"\"/>"<<endl; + file<<"\t\t\t<point xPos=\""<<x2<<"\" yPos=\""<<y2<<"\"/>"<<endl; + file<<"\t\t</wall>"<<endl; + } + + } + file<<endl; + + for(unsigned int i=0; i<_edges.size(); i++) { + JEdge* edge=_edges[i]; + + if(edge->pNode0==node_id || edge->pNode1==node_id) { + double x1=edge->pStart.pPos.GetX()*factor-centre._x; + double y1=edge->pStart.pPos.GetY()*factor-centre._y; + double x2=edge->pEnd.pPos.GetX()*factor-centre._x; + double y2=edge->pEnd.pPos.GetY()*factor-centre._y; + + file<<"\t\t<label centerX=\""<<0.5*(x1+x2)<<"\" centerY=\""<<0.5*(y1+y2)<<"\" centerZ=\"0\" text=\""<<edge->id<<"\" color=\"20\" />"<<endl; + file<<"\t\t<door id = \""<<i<<"\">"<<endl; + file<<"\t\t\t<point xPos=\""<<x1<<"\" yPos=\""<<y1<<"\"/>"<<endl; + file<<"\t\t\t<point xPos=\""<<x2<<"\" yPos=\""<<y2<<"\"/>"<<endl; + file<<"\t\t</door>"<<endl; + } + } + + file<<endl; + } + + //eventually write any goal + for (map<int, Goal*>::const_iterator itr = _building->GetAllGoals().begin(); + itr != _building->GetAllGoals().end(); ++itr) { + + //int door=itr->first; + Goal* goal = itr->second; + file<<goal->Write()<<endl; + } + output=file.str(); } -void NavMesh::WriteToFileTraVisTo(std::string fileName) { - ofstream file(fileName.c_str()); - file.precision(2); - file<<fixed; - - - if(file.is_open()==false){ - Log->Write("\tERROR:\tcould not open the file: " + fileName +" for writing the mesh"); - return; - } - - //writing the header - file<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl - <<"<trajectoriesDataset>"<<endl - <<"\t<header formatVersion = \"1.0\">"<<endl - <<"\t\t<agents>3</agents>"<<endl - <<"\t\t<seed>0</seed>"<<endl - <<"\t\t<frameRate>10</frameRate>"<<endl - <<"\t</header>"<<endl - <<endl - <<endl; - - //writing the geometry - string output; - WriteToString(output); - file<<"\t<geometry>"<<endl; - file<<output<<endl; - file<<"\t</geometry>"<<endl; - file.close(); +void NavMesh::WriteToFileTraVisTo(std::string fileName) +{ + ofstream file(fileName.c_str()); + file.precision(2); + file<<fixed; + + + if(file.is_open()==false) { + Log->Write("\tERROR:\tcould not open the file: " + fileName +" for writing the mesh"); + return; + } + + //writing the header + file<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl + <<"<trajectoriesDataset>"<<endl + <<"\t<header formatVersion = \"1.0\">"<<endl + <<"\t\t<agents>3</agents>"<<endl + <<"\t\t<seed>0</seed>"<<endl + <<"\t\t<frameRate>10</frameRate>"<<endl + <<"\t</header>"<<endl + <<endl + <<endl; + + //writing the geometry + string output; + WriteToString(output); + file<<"\t<geometry>"<<endl; + file<<output<<endl; + file<<"\t</geometry>"<<endl; + file.close(); } -void NavMesh::WriteToFileTraVisTo(std::string fileName, const std::vector<Point>& points) { - ofstream file(fileName.c_str()); - file.precision(2); - file<<fixed; - - //Point centre (10299,2051); - Point centre (0,0); - double factor=100; - - if(file.is_open()==false){ - cout <<"could not open the file: "<<fileName<<endl; - return; - } - - //writing the header - file<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl - <<"<trajectoriesDataset>"<<endl - <<"\t<header formatVersion = \"1.0\">"<<endl - <<"\t\t<agents>3</agents>"<<endl - <<"\t\t<seed>0</seed>"<<endl - <<"\t\t<frameRate>10</frameRate>"<<endl - <<"\t</header>"<<endl - <<endl - <<endl - <<"\t<geometry>"<<endl; - - - - for(unsigned int i=0;i<points.size();i++){ - - unsigned int size= points.size(); - double x1=points[ i%size].GetX()*factor -centre._x; - double y1=points[ i%size].GetY()*factor -centre._y; - double x2=points[ (i+1)%size].GetX()*factor -centre._x; - double y2=points[ (i+1)%size].GetY()*factor -centre._y; - - // draw the convex hull - file<<" \t\t<sphere centerX=\""<<x1<<"\" centerY=\""<<y1<<"\" centerZ=\"0\" radius=\"150\" color=\"100\" />"<<endl; - file<<"\t\t<label centerX=\""<<x1<<"\" centerY=\""<<y1<<"\" centerZ=\"0\" text=\""<<i<<"\" color=\"20\" />"<<endl; - file<<"\t\t<label centerX=\""<<0.5*(x1+x2)<<"\" centerY=\""<<0.5*(y1+y2)<<"\" centerZ=\"0\" text=\""<<i<<"\" color=\"180\" />"<<endl; - file<<"\t\t<wall id = \""<<i<<"\">"<<endl; - file<<"\t\t\t<point xPos=\""<<x1<<"\" yPos=\""<<y1<<"\"/>"<<endl; - file<<"\t\t\t<point xPos=\""<<x2<<"\" yPos=\""<<y2<<"\"/>"<<endl; - file<<"\t\t</wall>"<<endl; - - // cout.precision(2); - // cout<<fixed; - // printf("polygon.push_back(Point_2(%f, %f));\n",x1,y1); - } - file<<endl; - - - file<<"\t</geometry>"<<endl; - file.close(); +void NavMesh::WriteToFileTraVisTo(std::string fileName, const std::vector<Point>& points) +{ + ofstream file(fileName.c_str()); + file.precision(2); + file<<fixed; + + //Point centre (10299,2051); + Point centre (0,0); + double factor=100; + + if(file.is_open()==false) { + cout <<"could not open the file: "<<fileName<<endl; + return; + } + + //writing the header + file<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl + <<"<trajectoriesDataset>"<<endl + <<"\t<header formatVersion = \"1.0\">"<<endl + <<"\t\t<agents>3</agents>"<<endl + <<"\t\t<seed>0</seed>"<<endl + <<"\t\t<frameRate>10</frameRate>"<<endl + <<"\t</header>"<<endl + <<endl + <<endl + <<"\t<geometry>"<<endl; + + + + for(unsigned int i=0; i<points.size(); i++) { + + unsigned int size= points.size(); + double x1=points[ i%size].GetX()*factor -centre._x; + double y1=points[ i%size].GetY()*factor -centre._y; + double x2=points[ (i+1)%size].GetX()*factor -centre._x; + double y2=points[ (i+1)%size].GetY()*factor -centre._y; + + // draw the convex hull + file<<" \t\t<sphere centerX=\""<<x1<<"\" centerY=\""<<y1<<"\" centerZ=\"0\" radius=\"150\" color=\"100\" />"<<endl; + file<<"\t\t<label centerX=\""<<x1<<"\" centerY=\""<<y1<<"\" centerZ=\"0\" text=\""<<i<<"\" color=\"20\" />"<<endl; + file<<"\t\t<label centerX=\""<<0.5*(x1+x2)<<"\" centerY=\""<<0.5*(y1+y2)<<"\" centerZ=\"0\" text=\""<<i<<"\" color=\"180\" />"<<endl; + file<<"\t\t<wall id = \""<<i<<"\">"<<endl; + file<<"\t\t\t<point xPos=\""<<x1<<"\" yPos=\""<<y1<<"\"/>"<<endl; + file<<"\t\t\t<point xPos=\""<<x2<<"\" yPos=\""<<y2<<"\"/>"<<endl; + file<<"\t\t</wall>"<<endl; + + // cout.precision(2); + // cout<<fixed; + // printf("polygon.push_back(Point_2(%f, %f));\n",x1,y1); + } + file<<endl; + + + file<<"\t</geometry>"<<endl; + file.close(); } -void NavMesh::WriteToFileTraVisTo(std::string fileName, JNode* node){ - - ofstream file(fileName.c_str()); - file.precision(2); - file<<fixed; - - //Point centre (10299,2051); - Point centre (0,0); - double factor=100; - - if(file.is_open()==false){ - cout <<"could not open the file: "<<fileName<<endl; - return; - } - - //writing the header - file<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl - <<"<trajectoriesDataset>"<<endl - <<"\t<header formatVersion = \"1.0\">"<<endl - <<"\t\t<agents>3</agents>"<<endl - <<"\t\t<seed>0</seed>"<<endl - <<"\t\t<frameRate>10</frameRate>"<<endl - <<"\t</header>"<<endl - <<endl - <<endl - <<"\t<geometry>"<<endl; - - - int node_id=node->id; //cout<<"node id: "<<node_id<<endl; - - file<<"\t\t<label centerX=\""<<node->pCentroid.GetX()*factor -centre._x<<"\" centerY=\""<<node->pCentroid.GetY()*factor-centre._y<<"\" centerZ=\"0\" text=\""<<node->id <<"\" color=\"100\" />"<<endl; - - // cout<<"size: "<< JNode->pHull.size()<<endl; - // std::sort(JNode->pHull.begin(), JNode->pHull.end()); - // JNode->pHull.erase(std::unique(JNode->pHull.begin(), JNode->pHull.end()), JNode->pHull.end()); - // cout<<"size: "<< JNode->pHull.size()<<endl; - - for(unsigned int i=0;i<node->pHull.size();i++){ - //double x=pVertices[JNode->pHull[i].id]->pPos.GetX()*factor -centre.pX; - //double y=pVertices[JNode->pHull[i].id]->pPos.GetY()*factor -centre.pY; - //file<<" \t\t<sphere centerX=\""<<x<<"\" centerY=\""<<y<<"\" centerZ=\"0\" radius=\"5\" color=\"100\" />"<<endl; - //file<<"\t\t<label centerX=\""<<x<<"\" centerY=\""<<y<<"\" centerZ=\"0\" text=\""<<JNode->pHull[i].id<<"\" color=\"20\" />"<<endl; - - // draw the convex hull - // unsigned int size= node->pHull.size(); - // file<<" \t\t<sphere centerX=\""<<x<<"\" centerY=\""<<y<<"\" centerZ=\"0\" radius=\"5\" color=\"100\" />"<<endl; - // file<<"\t\t<label centerX=\""<<x<<"\" centerY=\""<<y<<"\" centerZ=\"0\" text=\""<<i<<"\" color=\"20\" />"<<endl; - // double x1=pVertices[node->pHull[i%size].id]->pPos.GetX()*factor -centre.pX; - // double y1=pVertices[node->pHull[i%size].id]->pPos.GetY()*factor -centre.pY; - // double x2=pVertices[node->pHull[(i+1)%size].id]->pPos.GetX()*factor -centre.pX; - // double y2=pVertices[node->pHull[(i+1)%size].id]->pPos.GetY()*factor -centre.pY; - // file<<"\t\t<wall id = \""<<i<<"\">"<<endl; - // file<<"\t\t\t<point xPos=\""<<x1<<"\" yPos=\""<<y1<<"\"/>"<<endl; - // file<<"\t\t\t<point xPos=\""<<x2<<"\" yPos=\""<<y2<<"\"/>"<<endl; - // file<<"\t\t</wall>"<<endl; - // cout.precision(2); - // cout<<fixed; - // printf("polygon.push_back(Point_2(%f, %f));\n",x1,y1); - } - file<<endl; - - for(unsigned int i=0;i<_obst.size();i++){ - JObstacle* obst=_obst[i]; - - if(obst->pNode0==node_id ){ - double x1=obst->pStart.pPos.GetX()*factor-centre._x; - double y1=obst->pStart.pPos.GetY()*factor-centre._y; - double x2=obst->pEnd.pPos.GetX()*factor-centre._x; - double y2=obst->pEnd.pPos.GetY()*factor-centre._y; - - file<<"\t\t<wall id = \""<<i<<"\">"<<endl; - file<<"\t\t\t<point xPos=\""<<x1<<"\" yPos=\""<<y1<<"\"/>"<<endl; - file<<"\t\t\t<point xPos=\""<<x2<<"\" yPos=\""<<y2<<"\"/>"<<endl; - file<<"\t\t</wall>"<<endl; - } - - } - file<<endl; - - for(unsigned int i=0;i<_edges.size();i++){ - JEdge* edge=_edges[i]; - - if(edge->pNode0==node_id || edge->pNode1==node_id){ - double x1=edge->pStart.pPos.GetX()*factor-centre._x; - double y1=edge->pStart.pPos.GetY()*factor-centre._y; - double x2=edge->pEnd.pPos.GetX()*factor-centre._x; - double y2=edge->pEnd.pPos.GetY()*factor-centre._y; - - file<<"\t\t<label centerX=\""<<0.5*(x1+x2)<<"\" centerY=\""<<0.5*(y1+y2)<<"\" centerZ=\"0\" text=\""<<edge->id<<"\" color=\"20\" />"<<endl; - file<<"\t\t<door id = \""<<i<<"\">"<<endl; - file<<"\t\t\t<point xPos=\""<<x1<<"\" yPos=\""<<y1<<"\"/>"<<endl; - file<<"\t\t\t<point xPos=\""<<x2<<"\" yPos=\""<<y2<<"\"/>"<<endl; - file<<"\t\t</door>"<<endl; - } - - } - - file<<endl; - - file<<"\t</geometry>"<<endl; - file.close(); +void NavMesh::WriteToFileTraVisTo(std::string fileName, JNode* node) +{ + + ofstream file(fileName.c_str()); + file.precision(2); + file<<fixed; + + //Point centre (10299,2051); + Point centre (0,0); + double factor=100; + + if(file.is_open()==false) { + cout <<"could not open the file: "<<fileName<<endl; + return; + } + + //writing the header + file<<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"<<endl + <<"<trajectoriesDataset>"<<endl + <<"\t<header formatVersion = \"1.0\">"<<endl + <<"\t\t<agents>3</agents>"<<endl + <<"\t\t<seed>0</seed>"<<endl + <<"\t\t<frameRate>10</frameRate>"<<endl + <<"\t</header>"<<endl + <<endl + <<endl + <<"\t<geometry>"<<endl; + + + int node_id=node->id; //cout<<"node id: "<<node_id<<endl; + + file<<"\t\t<label centerX=\""<<node->pCentroid.GetX()*factor -centre._x<<"\" centerY=\""<<node->pCentroid.GetY()*factor-centre._y<<"\" centerZ=\"0\" text=\""<<node->id <<"\" color=\"100\" />"<<endl; + + // cout<<"size: "<< JNode->pHull.size()<<endl; + // std::sort(JNode->pHull.begin(), JNode->pHull.end()); + // JNode->pHull.erase(std::unique(JNode->pHull.begin(), JNode->pHull.end()), JNode->pHull.end()); + // cout<<"size: "<< JNode->pHull.size()<<endl; + + for(unsigned int i=0; i<node->pHull.size(); i++) { + //double x=pVertices[JNode->pHull[i].id]->pPos.GetX()*factor -centre.pX; + //double y=pVertices[JNode->pHull[i].id]->pPos.GetY()*factor -centre.pY; + //file<<" \t\t<sphere centerX=\""<<x<<"\" centerY=\""<<y<<"\" centerZ=\"0\" radius=\"5\" color=\"100\" />"<<endl; + //file<<"\t\t<label centerX=\""<<x<<"\" centerY=\""<<y<<"\" centerZ=\"0\" text=\""<<JNode->pHull[i].id<<"\" color=\"20\" />"<<endl; + + // draw the convex hull + // unsigned int size= node->pHull.size(); + // file<<" \t\t<sphere centerX=\""<<x<<"\" centerY=\""<<y<<"\" centerZ=\"0\" radius=\"5\" color=\"100\" />"<<endl; + // file<<"\t\t<label centerX=\""<<x<<"\" centerY=\""<<y<<"\" centerZ=\"0\" text=\""<<i<<"\" color=\"20\" />"<<endl; + // double x1=pVertices[node->pHull[i%size].id]->pPos.GetX()*factor -centre.pX; + // double y1=pVertices[node->pHull[i%size].id]->pPos.GetY()*factor -centre.pY; + // double x2=pVertices[node->pHull[(i+1)%size].id]->pPos.GetX()*factor -centre.pX; + // double y2=pVertices[node->pHull[(i+1)%size].id]->pPos.GetY()*factor -centre.pY; + // file<<"\t\t<wall id = \""<<i<<"\">"<<endl; + // file<<"\t\t\t<point xPos=\""<<x1<<"\" yPos=\""<<y1<<"\"/>"<<endl; + // file<<"\t\t\t<point xPos=\""<<x2<<"\" yPos=\""<<y2<<"\"/>"<<endl; + // file<<"\t\t</wall>"<<endl; + // cout.precision(2); + // cout<<fixed; + // printf("polygon.push_back(Point_2(%f, %f));\n",x1,y1); + } + file<<endl; + + for(unsigned int i=0; i<_obst.size(); i++) { + JObstacle* obst=_obst[i]; + + if(obst->pNode0==node_id ) { + double x1=obst->pStart.pPos.GetX()*factor-centre._x; + double y1=obst->pStart.pPos.GetY()*factor-centre._y; + double x2=obst->pEnd.pPos.GetX()*factor-centre._x; + double y2=obst->pEnd.pPos.GetY()*factor-centre._y; + + file<<"\t\t<wall id = \""<<i<<"\">"<<endl; + file<<"\t\t\t<point xPos=\""<<x1<<"\" yPos=\""<<y1<<"\"/>"<<endl; + file<<"\t\t\t<point xPos=\""<<x2<<"\" yPos=\""<<y2<<"\"/>"<<endl; + file<<"\t\t</wall>"<<endl; + } + + } + file<<endl; + + for(unsigned int i=0; i<_edges.size(); i++) { + JEdge* edge=_edges[i]; + + if(edge->pNode0==node_id || edge->pNode1==node_id) { + double x1=edge->pStart.pPos.GetX()*factor-centre._x; + double y1=edge->pStart.pPos.GetY()*factor-centre._y; + double x2=edge->pEnd.pPos.GetX()*factor-centre._x; + double y2=edge->pEnd.pPos.GetY()*factor-centre._y; + + file<<"\t\t<label centerX=\""<<0.5*(x1+x2)<<"\" centerY=\""<<0.5*(y1+y2)<<"\" centerZ=\"0\" text=\""<<edge->id<<"\" color=\"20\" />"<<endl; + file<<"\t\t<door id = \""<<i<<"\">"<<endl; + file<<"\t\t\t<point xPos=\""<<x1<<"\" yPos=\""<<y1<<"\"/>"<<endl; + file<<"\t\t\t<point xPos=\""<<x2<<"\" yPos=\""<<y2<<"\"/>"<<endl; + file<<"\t\t</door>"<<endl; + } + + } + + file<<endl; + + file<<"\t</geometry>"<<endl; + file.close(); } -void NavMesh::WriteToFile(std::string fileName) { - - ofstream file(fileName.c_str()); - file.precision(2); - file<<fixed; - - if(file.is_open()==false){ - cout <<"could not open the file: "<<fileName<<endl; - return; - } - - //write the vertices - //file<<"# vertices section"<<endl; - file<<_vertices.size()<<endl; - for (unsigned int v=0;v<_vertices.size();v++){ - file<<"\t"<<_vertices[v]->pPos.GetX()<<" " <<_vertices[v]->pPos.GetY()<<endl; - - } - - //write the edges - //file<<endl<<"# edges section"<<endl; - file<<_edges.size()<<endl; - for (unsigned int e=0;e<_edges.size();e++){ - //file<<pEdges[e]->pStart.pPos.GetX()<<" " <<pEdges[e]->pStart.pPos.GetY()<<endl; - //file<<"\t"<<pEdges[e]->pDisp.GetX()<<" " <<pEdges[e]->pDisp.GetY()<<endl; - file<<"\t"; - file<<_edges[e]->pStart.id<<" " <<_edges[e]->pEnd.id<<" "; - file<<_edges[e]->pNode0<<" " <<_edges[e]->pNode1<<endl; - } - - - //write the obstacles - //file<<endl<<"# Obstacles section"<<endl; - file<<_obst.size()<<endl; - for (unsigned int ob=0;ob<_obst.size();ob++){ - file<<"\t"; - file<<_obst[ob]->pStart.id<<" " <<_obst[ob]->pEnd.id<<" "; - file<<_obst[ob]->pNode0<<" "<<_obst[ob]->pNextObst<<endl; - } - - //write the nodes - //file<<endl<<"# Nodes section"<<endl; - - std::map<string,int> ngroup_to_size; - for (unsigned int n=0;n<_nodes.size();n++){ - ngroup_to_size[_nodes[n]->pGroup]++; - } - - string previousGroup= _nodes[0]->pGroup; - file<<endl<<previousGroup<<endl; - file<<ngroup_to_size[previousGroup]<<""; - - for (unsigned int n=0;n<_nodes.size();n++){ - JNode* JNode=_nodes[n]; - string actualGroup=JNode->pGroup; - if(actualGroup!=previousGroup){ - previousGroup=actualGroup; - //file<<"# JNode group"<<endl; - file<<endl<<previousGroup<<endl; - file<<ngroup_to_size[previousGroup]<<""; - } - - //assert(JNode->pObstacles.size()<20); - //assert(JNode->pPortals.size()<20); - //file<<"nodeid "<<JNode->id<<endl; - file<<endl; - file<<"\t"<<JNode->pCentroid.GetX()<<" "<<JNode->pCentroid.GetY()<<endl; - file<<"\t"<<JNode->pHull.size()<<" "; - for(unsigned int i=0;i<JNode->pHull.size();i++){ - file<<JNode->pHull[i].id<<" "; - } - file<<endl; - file<<"\t"<<JNode->pNormalVec[0]<<" "<<JNode->pNormalVec[1]<<" "<<JNode->pNormalVec[2]<<endl; - - - file<<"\t"<<JNode->pPortals.size()<<" "; - for(unsigned int i=0;i<JNode->pPortals.size();i++){ - file<<JNode->pPortals[i]<<" "; - } - file<<endl; - - file<<"\t"<<JNode->pObstacles.size()<<" "; - for(unsigned int i=0;i<JNode->pObstacles.size();i++){ - file<<JNode->pObstacles[i]<<" "; - } - - file<<endl; - } - - file.close(); +void NavMesh::WriteToFile(std::string fileName) +{ + + ofstream file(fileName.c_str()); + file.precision(2); + file<<fixed; + + if(file.is_open()==false) { + cout <<"could not open the file: "<<fileName<<endl; + return; + } + + //write the vertices + //file<<"# vertices section"<<endl; + file<<_vertices.size()<<endl; + for (unsigned int v=0; v<_vertices.size(); v++) { + file<<"\t"<<_vertices[v]->pPos.GetX()<<" " <<_vertices[v]->pPos.GetY()<<endl; + + } + + //write the edges + //file<<endl<<"# edges section"<<endl; + file<<_edges.size()<<endl; + for (unsigned int e=0; e<_edges.size(); e++) { + //file<<pEdges[e]->pStart.pPos.GetX()<<" " <<pEdges[e]->pStart.pPos.GetY()<<endl; + //file<<"\t"<<pEdges[e]->pDisp.GetX()<<" " <<pEdges[e]->pDisp.GetY()<<endl; + file<<"\t"; + file<<_edges[e]->pStart.id<<" " <<_edges[e]->pEnd.id<<" "; + file<<_edges[e]->pNode0<<" " <<_edges[e]->pNode1<<endl; + } + + + //write the obstacles + //file<<endl<<"# Obstacles section"<<endl; + file<<_obst.size()<<endl; + for (unsigned int ob=0; ob<_obst.size(); ob++) { + file<<"\t"; + file<<_obst[ob]->pStart.id<<" " <<_obst[ob]->pEnd.id<<" "; + file<<_obst[ob]->pNode0<<" "<<_obst[ob]->pNextObst<<endl; + } + + //write the nodes + //file<<endl<<"# Nodes section"<<endl; + + std::map<string,int> ngroup_to_size; + for (unsigned int n=0; n<_nodes.size(); n++) { + ngroup_to_size[_nodes[n]->pGroup]++; + } + + string previousGroup= _nodes[0]->pGroup; + file<<endl<<previousGroup<<endl; + file<<ngroup_to_size[previousGroup]<<""; + + for (unsigned int n=0; n<_nodes.size(); n++) { + JNode* JNode=_nodes[n]; + string actualGroup=JNode->pGroup; + if(actualGroup!=previousGroup) { + previousGroup=actualGroup; + //file<<"# JNode group"<<endl; + file<<endl<<previousGroup<<endl; + file<<ngroup_to_size[previousGroup]<<""; + } + + //assert(JNode->pObstacles.size()<20); + //assert(JNode->pPortals.size()<20); + //file<<"nodeid "<<JNode->id<<endl; + file<<endl; + file<<"\t"<<JNode->pCentroid.GetX()<<" "<<JNode->pCentroid.GetY()<<endl; + file<<"\t"<<JNode->pHull.size()<<" "; + for(unsigned int i=0; i<JNode->pHull.size(); i++) { + file<<JNode->pHull[i].id<<" "; + } + file<<endl; + file<<"\t"<<JNode->pNormalVec[0]<<" "<<JNode->pNormalVec[1]<<" "<<JNode->pNormalVec[2]<<endl; + + + file<<"\t"<<JNode->pPortals.size()<<" "; + for(unsigned int i=0; i<JNode->pPortals.size(); i++) { + file<<JNode->pPortals[i]<<" "; + } + file<<endl; + + file<<"\t"<<JNode->pObstacles.size()<<" "; + for(unsigned int i=0; i<JNode->pObstacles.size(); i++) { + file<<JNode->pObstacles[i]<<" "; + } + + file<<endl; + } + + file.close(); } -int NavMesh::AddVertex(JVertex* v) { - for (unsigned int vc = 0; vc < _vertices.size(); vc++) { - if (_vertices[vc]->pPos.operator ==(v->pPos)) { +int NavMesh::AddVertex(JVertex* v) +{ + for (unsigned int vc = 0; vc < _vertices.size(); vc++) { + if (_vertices[vc]->pPos.operator ==(v->pPos)) { #ifdef _DEBUG - cout << "JVertex already present:" << _vertices[vc]->id << endl; + cout << "JVertex already present:" << _vertices[vc]->id << endl; #endif - return -1; - } - } - if (_vertices.size() == 0) { - v->id = 0; - } else { - v->id = _vertices[_vertices.size() - 1]->id + 1; - } - _vertices.push_back(v); - return v->id; + return -1; + } + } + if (_vertices.size() == 0) { + v->id = 0; + } else { + v->id = _vertices[_vertices.size() - 1]->id + 1; + } + _vertices.push_back(v); + return v->id; } -int NavMesh::AddEdge(JEdge* e) { - int id = IsPortal(e->pStart.pPos, e->pEnd.pPos); - - if ((IsElementInVector(_edges, e) == false) && (id == -1)) { - if (_edges.size() == 0) { - e->id = 0; - } else { - e->id = _edges[_edges.size() - 1]->id + 1; - } - _edges.push_back(e); - return e->id; - } else { +int NavMesh::AddEdge(JEdge* e) +{ + int id = IsPortal(e->pStart.pPos, e->pEnd.pPos); + + if ((IsElementInVector(_edges, e) == false) && (id == -1)) { + if (_edges.size() == 0) { + e->id = 0; + } else { + e->id = _edges[_edges.size() - 1]->id + 1; + } + _edges.push_back(e); + return e->id; + } else { #ifdef _DEBUG - cout << "JEdge already present:" << id << endl; + cout << "JEdge already present:" << id << endl; #endif - } + } - return -1; + return -1; } -int NavMesh::AddObst(JObstacle* o) { - int id= IsObstacle(o->pStart.pPos, o->pEnd.pPos); - - if ( (IsElementInVector(_obst, o) == false) && - (id==-1 )){ - if (_obst.size() == 0) { - o->id = 0; - } else { - o->id = _obst[_obst.size() - 1]->id + 1; - } - _obst.push_back(o); - return o->id; - } else { +int NavMesh::AddObst(JObstacle* o) +{ + int id= IsObstacle(o->pStart.pPos, o->pEnd.pPos); + + if ( (IsElementInVector(_obst, o) == false) && + (id==-1 )) { + if (_obst.size() == 0) { + o->id = 0; + } else { + o->id = _obst[_obst.size() - 1]->id + 1; + } + _obst.push_back(o); + return o->id; + } else { #ifdef _DEBUG - cout << "Obstacles already present:" << id << endl; + cout << "Obstacles already present:" << id << endl; #endif - } + } - return -1; + return -1; } -int NavMesh::AddNode(JNode* node) { +int NavMesh::AddNode(JNode* node) +{ - std::sort(node->pObstacles.begin(),node->pObstacles.end()); - std::sort(node->pPortals.begin(),node->pPortals.end()); + std::sort(node->pObstacles.begin(),node->pObstacles.end()); + std::sort(node->pPortals.begin(),node->pPortals.end()); - for(unsigned int n=0;n<_nodes.size();n++){ - if(*_nodes[n]==*node) { + for(unsigned int n=0; n<_nodes.size(); n++) { + if(*_nodes[n]==*node) { #ifdef _DEBUG - cout << "JNode already present:" << node->id << endl; + cout << "JNode already present:" << node->id << endl; #endif - assert(0); - return -1; - } - } + assert(0); + return -1; + } + } - if (IsElementInVector(_nodes, node)) { + if (IsElementInVector(_nodes, node)) { #ifdef _DEBUG - cout << "JNode already present:" << node->id << endl; + cout << "JNode already present:" << node->id << endl; #endif - assert(0); - return -1; - } - - if (_nodes.size() == 0) { - node->id = 0; - } else { - node->id = _nodes[_nodes.size() - 1]->id + 1; - } - _nodes.push_back(node); - return node->id; + assert(0); + return -1; + } + + if (_nodes.size() == 0) { + node->id = 0; + } else { + node->id = _nodes[_nodes.size() - 1]->id + 1; + } + _nodes.push_back(node); + return node->id; } -NavMesh::JVertex* NavMesh::GetVertex(const Point& p) { +NavMesh::JVertex* NavMesh::GetVertex(const Point& p) +{ - for(unsigned int v=0;v<_vertices.size();v++){ - if(_vertices[v]->pPos.operator ==(p)){ - return _vertices[v]; - } - } + for(unsigned int v=0; v<_vertices.size(); v++) { + if(_vertices[v]->pPos.operator ==(p)) { + return _vertices[v]; + } + } #ifdef _DEBUG - cout<<"JVertex not found: "<< p.GetX()<<":"<<p.GetY()<<endl; - cout<<"Adding "<<endl; - cout<<"pVertices.size()="<<_vertices.size()<<endl; + cout<<"JVertex not found: "<< p.GetX()<<":"<<p.GetY()<<endl; + cout<<"Adding "<<endl; + cout<<"pVertices.size()="<<_vertices.size()<<endl; #endif - JVertex* v = new JVertex(); - v->pPos= p; - AddVertex(v); - //this could lead to an infinite loop if the point cannot be added and cannot be found - return GetVertex(p); + JVertex* v = new JVertex(); + v->pPos= p; + AddVertex(v); + //this could lead to an infinite loop if the point cannot be added and cannot be found + return GetVertex(p); - //exit(EXIT_FAILURE); + //exit(EXIT_FAILURE); } -int NavMesh::IsPortal(Point& p1, Point& p2) { +int NavMesh::IsPortal(Point& p1, Point& p2) +{ - for(unsigned int i=0;i<_edges.size();i++){ - JEdge* e=_edges[i]; + for(unsigned int i=0; i<_edges.size(); i++) { + JEdge* e=_edges[i]; - if( (e->pStart.pPos==p1) && (e->pEnd.pPos==p2)){ - return e->id; - } + if( (e->pStart.pPos==p1) && (e->pEnd.pPos==p2)) { + return e->id; + } - if( (e->pStart.pPos==p2) && (e->pEnd.pPos==p1)){ - return e->id; - } - } - return -1; + if( (e->pStart.pPos==p2) && (e->pEnd.pPos==p1)) { + return e->id; + } + } + return -1; } -void NavMesh::FinalizeAlphaShape(){ - Log->Write("INFO:\tFinalizing the mesh with an Alpha Shape"); - - // WriteToFileTraVisTo("arena_envelope.xml",envelope); - //collect all possible vertices that form that envelope +void NavMesh::FinalizeAlphaShape() +{ + Log->Write("INFO:\tFinalizing the mesh with an Alpha Shape"); - vector<Line> envelope; + // WriteToFileTraVisTo("arena_envelope.xml",envelope); + //collect all possible vertices that form that envelope - Room* outside = _building->GetRoom("outside"); - if(outside==NULL){ - Log->Write("INFO:\t there is no outside room for constructing the alpha shape"); - exit(EXIT_FAILURE); - } + vector<Line> envelope; - const Point& env_center=outside->GetSubRoom(0)->GetCentroid(); - double env_radius= outside->GetSubRoom(0)->GetWall(0).DistTo(env_center); - //outside->WriteToErrorLog(); - //cout<<"Center:" <<env_center.toString()<<endl; - //cout<<"Radius:" <<env_radius<<endl; exit(0); + Room* outside = _building->GetRoom("outside"); + if(outside==NULL) { + Log->Write("INFO:\t there is no outside room for constructing the alpha shape"); + exit(EXIT_FAILURE); + } + const Point& env_center=outside->GetSubRoom(0)->GetCentroid(); + double env_radius= outside->GetSubRoom(0)->GetWall(0).DistTo(env_center); + //outside->WriteToErrorLog(); + //cout<<"Center:" <<env_center.toString()<<endl; + //cout<<"Radius:" <<env_radius<<endl; exit(0); - double xmin=0.1; - double xmax= 50.0; - double ymin=0.1; - double ymax= 44.0; - - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* r = _building->GetRoom(i); - string caption = r->GetCaption(); - - //skip the virtual room containing the complete geometry - if(r->GetCaption()=="outside") continue; - const Point& centroid0 = Point(0,0); - for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { - SubRoom* s = r->GetSubRoom(k); + double xmin=0.1; + double xmax= 50.0; + double ymin=0.1; + double ymax= 44.0; + + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* r = _building->GetRoom(i); + string caption = r->GetCaption(); + + //skip the virtual room containing the complete geometry + if(r->GetCaption()=="outside") continue; + const Point& centroid0 = Point(0,0); + + for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { + SubRoom* s = r->GetSubRoom(k); - //walls - const vector<Wall>& walls = s->GetAllWalls(); + //walls + const vector<Wall>& walls = s->GetAllWalls(); - for (unsigned w = 0; w < walls.size(); w++) { + for (unsigned w = 0; w < walls.size(); w++) { - //FIXME: this method is more general but is not working - //if(IsCircleVisibleFromLine(env_center,env_radius,walls[w])==false) continue; + //FIXME: this method is more general but is not working + //if(IsCircleVisibleFromLine(env_center,env_radius,walls[w])==false) continue; - Point pt1= walls[w].GetPoint1(); - Point pt2= walls[w].GetPoint2(); + Point pt1= walls[w].GetPoint1(); + Point pt2= walls[w].GetPoint2(); - if( (xmin < pt1._x) && (pt1._x < xmax) && - (ymin < pt1._y) && (pt1._y < ymax) ) continue; + if( (xmin < pt1._x) && (pt1._x < xmax) && + (ymin < pt1._y) && (pt1._y < ymax) ) continue; - if( (xmin < pt2._x) && (pt2._x < xmax) && - (ymin < pt2._y) && (pt2._y < ymax) ) continue; + if( (xmin < pt2._x) && (pt2._x < xmax) && + (ymin < pt2._y) && (pt2._y < ymax) ) continue; - //first attempt - Point P0 = walls[w].GetPoint1(); - Point P1 = walls[w].GetPoint2(); - Point D0 = P1 - P0; - Point D1 = centroid0-P0; - if (D0.Det(D1) < 0) { - envelope.push_back(Line(P0, P1)); - }else{ - envelope.push_back(Line(P1, P0)); - } - } + //first attempt + Point P0 = walls[w].GetPoint1(); + Point P1 = walls[w].GetPoint2(); + Point D0 = P1 - P0; + Point D1 = centroid0-P0; + if (D0.Det(D1) < 0) { + envelope.push_back(Line(P0, P1)); + } else { + envelope.push_back(Line(P1, P0)); + } + } - const vector<Transition*>& transitions = s->GetAllTransitions(); - for (unsigned t = 0; t < transitions.size(); t++) { + const vector<Transition*>& transitions = s->GetAllTransitions(); + for (unsigned t = 0; t < transitions.size(); t++) { - //if(IsCircleVisibleFromLine(env_center,env_radius,*transitions[t])==false) continue; + //if(IsCircleVisibleFromLine(env_center,env_radius,*transitions[t])==false) continue; - Point pt1= transitions[t]->GetPoint1(); - Point pt2= transitions[t]->GetPoint2(); + Point pt1= transitions[t]->GetPoint1(); + Point pt2= transitions[t]->GetPoint2(); - if( (xmin < pt1._x) && (pt1._x < xmax) && - (ymin < pt1._y) && (pt1._y < ymax) ) continue; + if( (xmin < pt1._x) && (pt1._x < xmax) && + (ymin < pt1._y) && (pt1._y < ymax) ) continue; - if( (xmin < pt2._x) && (pt2._x < xmax) && - (ymin < pt2._y) && (pt2._y < ymax) ) continue; + if( (xmin < pt2._x) && (pt2._x < xmax) && + (ymin < pt2._y) && (pt2._y < ymax) ) continue; - //first attempt - Point P0 = transitions[t]->GetPoint1(); - Point P1 = transitions[t]->GetPoint2(); - Point D0 = P1 - P0; - Point D1 = centroid0-P0; - if (D0.Det(D1) < 0) { - envelope.push_back(Line(P0, P1)); - }else{ - envelope.push_back(Line(P1, P0)); - } - } - } - } + //first attempt + Point P0 = transitions[t]->GetPoint1(); + Point P1 = transitions[t]->GetPoint2(); + Point D0 = P1 - P0; + Point D1 = centroid0-P0; + if (D0.Det(D1) < 0) { + envelope.push_back(Line(P0, P1)); + } else { + envelope.push_back(Line(P1, P0)); + } + } + } + } - vector<Point> env; - for(unsigned int i=0;i<envelope.size();i++){ - env.push_back(envelope[i].GetPoint1()); - env.push_back(envelope[i].GetPoint2()); - } - - //WriteToFileTraVisTo("jst_test_ulrich.xml",env); - //cout<<"done"<<endl; - //cout<<"env size: "<<envelope.size()<<endl; - // exit(0); - - //link those vertices - vector<Point> Hull; - Hull.push_back(envelope[envelope.size()-1].GetPoint1()); - Hull.push_back(envelope[envelope.size()-1].GetPoint2()); - envelope.pop_back(); - - while(envelope.empty()==false){ - for(unsigned int i=0;i<envelope.size();i++){ - if(envelope[i].GetPoint1()==Hull[Hull.size()-1]){ - Hull.push_back(envelope[i].GetPoint2()); - envelope.erase(envelope.begin()+i); - } else if(envelope[i].GetPoint2()==Hull[Hull.size()-1]) - { - Hull.push_back(envelope[i].GetPoint1()); - envelope.erase(envelope.begin()+i); - } - } - } - - //eject the last point which is a duplicate. - Hull.pop_back(); - - //the surrounding room - vector<Point> Hull2=_building->GetRoom("outside")->GetSubRoom(0)->GetPolygon(); + vector<Point> env; + for(unsigned int i=0; i<envelope.size(); i++) { + env.push_back(envelope[i].GetPoint1()); + env.push_back(envelope[i].GetPoint2()); + } + + //WriteToFileTraVisTo("jst_test_ulrich.xml",env); + //cout<<"done"<<endl; + //cout<<"env size: "<<envelope.size()<<endl; + // exit(0); + + //link those vertices + vector<Point> Hull; + Hull.push_back(envelope[envelope.size()-1].GetPoint1()); + Hull.push_back(envelope[envelope.size()-1].GetPoint2()); + envelope.pop_back(); + + while(envelope.empty()==false) { + for(unsigned int i=0; i<envelope.size(); i++) { + if(envelope[i].GetPoint1()==Hull[Hull.size()-1]) { + Hull.push_back(envelope[i].GetPoint2()); + envelope.erase(envelope.begin()+i); + } else if(envelope[i].GetPoint2()==Hull[Hull.size()-1]) { + Hull.push_back(envelope[i].GetPoint1()); + envelope.erase(envelope.begin()+i); + } + } + } + + //eject the last point which is a duplicate. + Hull.pop_back(); + + //the surrounding room + vector<Point> Hull2=_building->GetRoom("outside")->GetSubRoom(0)->GetPolygon(); #ifdef _CGAL - //print for some check - //WriteToFileTraVisTo("arena_envelope.xml",Hull); - //exit(0); - //now check the polygon with holes. - - // { - // ofstream myfile ("mypoints.pts"); - // if (myfile.is_open()) - // { - // //quick testing - // for(unsigned int i=0;i<Hull2.size();i++){ - // myfile <<"P "<<Hull2[i].pX <<" "<<Hull2[i].pY<<endl; - // } - // myfile <<"H "<<Hull[0].pX <<" "<<Hull[0].pY<<endl; - // for(unsigned int i=1;i<Hull.size();i++){ - // myfile <<"P "<<Hull[i].pX <<" "<<Hull[i].pY<<endl; - // } - // } - // - // } - //WriteToFileTraVisTo("arena_envelope.xml",Hull); - - //perform some tests using CGAL - - //first polygon - Polygon_2 polygon2; - Polygon_2 holesP[1]; - - - for(unsigned int i=0;i<Hull.size();i++){ - holesP[0].push_back(Point_2(Hull[i]._x,Hull[i]._y)); - } - - for(unsigned int i=0;i<Hull2.size();i++){ - polygon2.push_back(Point_2(Hull2[i]._x,Hull2[i]._y)); - } - - if(holesP[0].is_clockwise_oriented())holesP[0].reverse_orientation(); - if(polygon2.is_clockwise_oriented())polygon2.reverse_orientation(); - - assert(holesP[0].is_counterclockwise_oriented()); - assert(polygon2.is_counterclockwise_oriented()); - assert(holesP[0].is_simple()); - assert(polygon2.is_simple()); + //print for some check + //WriteToFileTraVisTo("arena_envelope.xml",Hull); + //exit(0); + //now check the polygon with holes. + + // { + // ofstream myfile ("mypoints.pts"); + // if (myfile.is_open()) + // { + // //quick testing + // for(unsigned int i=0;i<Hull2.size();i++){ + // myfile <<"P "<<Hull2[i].pX <<" "<<Hull2[i].pY<<endl; + // } + // myfile <<"H "<<Hull[0].pX <<" "<<Hull[0].pY<<endl; + // for(unsigned int i=1;i<Hull.size();i++){ + // myfile <<"P "<<Hull[i].pX <<" "<<Hull[i].pY<<endl; + // } + // } + // + // } + //WriteToFileTraVisTo("arena_envelope.xml",Hull); + + //perform some tests using CGAL + + //first polygon + Polygon_2 polygon2; + Polygon_2 holesP[1]; + + + for(unsigned int i=0; i<Hull.size(); i++) { + holesP[0].push_back(Point_2(Hull[i]._x,Hull[i]._y)); + } + + for(unsigned int i=0; i<Hull2.size(); i++) { + polygon2.push_back(Point_2(Hull2[i]._x,Hull2[i]._y)); + } + + if(holesP[0].is_clockwise_oriented())holesP[0].reverse_orientation(); + if(polygon2.is_clockwise_oriented())polygon2.reverse_orientation(); + + assert(holesP[0].is_counterclockwise_oriented()); + assert(polygon2.is_counterclockwise_oriented()); + assert(holesP[0].is_simple()); + assert(polygon2.is_simple()); #endif //_CGAL - Log->Write("INFO:\tPerforming final triangulation with the outside!"); - - DTriangulation* tri= new DTriangulation(); - tri->SetOuterPolygone(Hull); - tri->AddHole(Hull2); - tri->Triangulate(); - vector<p2t::Triangle*> triangles=tri->GetTriangles(); - - // CGAL::Geomview_stream gv(CGAL::Bbox_3(-100, -100, -100, 100, 100, 100)); - // gv.set_line_width(4); - // gv.set_trace(true); - // gv.set_bg_color(CGAL::Color(0, 200, 200)); - // // gv.clear(); - // - // // use different colors, and put a few sleeps/clear. - // gv << CGAL::BLUE; - // gv.set_wired(true); - - for(unsigned int t=0;t<triangles.size();t++){ - p2t::Triangle* tr =triangles[t]; - - // Point_2 P0 = Point_2 (tr->GetPoint(0)->x,tr->GetPoint(0)->y); - // Point_2 P1 = Point_2 (tr->GetPoint(1)->x,tr->GetPoint(1)->y); - // Point_2 P2 = Point_2 (tr->GetPoint(2)->x,tr->GetPoint(2)->y); - // gv << Segment_2(P0,P1); - // gv << Segment_2(P1,P2); - // gv << Segment_2(P0,P2); - - Point P0 = Point (tr->GetPoint(0)->x,tr->GetPoint(0)->y); - Point P1 = Point (tr->GetPoint(1)->x,tr->GetPoint(1)->y); - Point P2 = Point (tr->GetPoint(2)->x,tr->GetPoint(2)->y); - - //create the new nodes - - JNode* new_node = new JNode(); - new_node->pGroup = "outside"; - //to get a correct ID - AddNode(new_node); - new_nodes.push_back(new_node); - new_node->pCentroid= (P0+P1+P2)*(1.0/3); - - new_node->pNormalVec[0]=0.0; - new_node->pNormalVec[1]=0.0; - new_node->pNormalVec[2]=0.0; - - // Points are by default counterclockwise - new_node->pHull.push_back(*(GetVertex(P0))); - new_node->pHull.push_back(*(GetVertex(P1))); - new_node->pHull.push_back(*(GetVertex(P2))); - - for (int index=0;index<3;index++){ - - Point P0 = Point (tr->GetPoint(index%3)->x,tr->GetPoint(index%3)->y); - Point P1 = Point (tr->GetPoint((index+1)%3)->x,tr->GetPoint((index+1)%3)->y); - - int edge_id=IsPortal(P0,P1); - if(edge_id != -1){ - //if(IsElementInVector(new_node->pPortals,edge_id)==false) - new_node->pPortals.push_back(edge_id); - - //invalidate any previous information - // they will be set later - JEdge* e = _edges[edge_id]; - e->pNode0=-1; - e->pNode1=-1; - } - - int obstacle_id=IsObstacle(P0,P1); - if(obstacle_id != -1){ - //std::cerr<<"Error: the convexification has created an JObstacle"<<endl; - //if(IsElementInVector(new_node->pObstacles,obstacle_id)==false) - new_node->pObstacles.push_back(obstacle_id); - - // FIXME 23 - //pObst[obstacle_id]->pNode0=new_node->id; - } - - // this portal was newly created - if ((obstacle_id==-1) && (edge_id==-1)){ - - JEdge* e= new JEdge(); - e->pEnd=*GetVertex(P1); - e->pStart= *GetVertex(P0); - AddEdge(e); - - //invalidate any previous information - // they will be set later - e->pNode0=-1; - e->pNode1=-1; - // caution: the ID is automatically assigned in the AddEdge method - //if(IsElementInVector(new_node->pPortals,edge_id)==false) - new_node->pPortals.push_back(e->id); - - } - } - } - - UpdateEdges(); - delete tri; - - Log->Write("INFO:\t...Done!"); + Log->Write("INFO:\tPerforming final triangulation with the outside!"); + + DTriangulation* tri= new DTriangulation(); + tri->SetOuterPolygone(Hull); + tri->AddHole(Hull2); + tri->Triangulate(); + vector<p2t::Triangle*> triangles=tri->GetTriangles(); + + // CGAL::Geomview_stream gv(CGAL::Bbox_3(-100, -100, -100, 100, 100, 100)); + // gv.set_line_width(4); + // gv.set_trace(true); + // gv.set_bg_color(CGAL::Color(0, 200, 200)); + // // gv.clear(); + // + // // use different colors, and put a few sleeps/clear. + // gv << CGAL::BLUE; + // gv.set_wired(true); + + for(unsigned int t=0; t<triangles.size(); t++) { + p2t::Triangle* tr =triangles[t]; + + // Point_2 P0 = Point_2 (tr->GetPoint(0)->x,tr->GetPoint(0)->y); + // Point_2 P1 = Point_2 (tr->GetPoint(1)->x,tr->GetPoint(1)->y); + // Point_2 P2 = Point_2 (tr->GetPoint(2)->x,tr->GetPoint(2)->y); + // gv << Segment_2(P0,P1); + // gv << Segment_2(P1,P2); + // gv << Segment_2(P0,P2); + + Point P0 = Point (tr->GetPoint(0)->x,tr->GetPoint(0)->y); + Point P1 = Point (tr->GetPoint(1)->x,tr->GetPoint(1)->y); + Point P2 = Point (tr->GetPoint(2)->x,tr->GetPoint(2)->y); + + //create the new nodes + + JNode* new_node = new JNode(); + new_node->pGroup = "outside"; + //to get a correct ID + AddNode(new_node); + new_nodes.push_back(new_node); + new_node->pCentroid= (P0+P1+P2)*(1.0/3); + + new_node->pNormalVec[0]=0.0; + new_node->pNormalVec[1]=0.0; + new_node->pNormalVec[2]=0.0; + + // Points are by default counterclockwise + new_node->pHull.push_back(*(GetVertex(P0))); + new_node->pHull.push_back(*(GetVertex(P1))); + new_node->pHull.push_back(*(GetVertex(P2))); + + for (int index=0; index<3; index++) { + + Point P0 = Point (tr->GetPoint(index%3)->x,tr->GetPoint(index%3)->y); + Point P1 = Point (tr->GetPoint((index+1)%3)->x,tr->GetPoint((index+1)%3)->y); + + int edge_id=IsPortal(P0,P1); + if(edge_id != -1) { + //if(IsElementInVector(new_node->pPortals,edge_id)==false) + new_node->pPortals.push_back(edge_id); + + //invalidate any previous information + // they will be set later + JEdge* e = _edges[edge_id]; + e->pNode0=-1; + e->pNode1=-1; + } + + int obstacle_id=IsObstacle(P0,P1); + if(obstacle_id != -1) { + //std::cerr<<"Error: the convexification has created an JObstacle"<<endl; + //if(IsElementInVector(new_node->pObstacles,obstacle_id)==false) + new_node->pObstacles.push_back(obstacle_id); + + // FIXME 23 + //pObst[obstacle_id]->pNode0=new_node->id; + } + + // this portal was newly created + if ((obstacle_id==-1) && (edge_id==-1)) { + + JEdge* e= new JEdge(); + e->pEnd=*GetVertex(P1); + e->pStart= *GetVertex(P0); + AddEdge(e); + + //invalidate any previous information + // they will be set later + e->pNode0=-1; + e->pNode1=-1; + // caution: the ID is automatically assigned in the AddEdge method + //if(IsElementInVector(new_node->pPortals,edge_id)==false) + new_node->pPortals.push_back(e->id); + + } + } + } + + UpdateEdges(); + delete tri; + + Log->Write("INFO:\t...Done!"); } -void NavMesh::Finalize() { - - Log->Write("INFO:\tFinalizing the mesh"); - - // WriteToFileTraVisTo("arena_envelope.xml",envelope); - //collect all possible vertices that form that envelope - - vector<Line> envelope; - vector<Point> centroids; - //centroids.push_back(Point(0,0)); - centroids.push_back(Point(60,40)); - centroids.push_back(Point(60,-40)); - centroids.push_back(Point(-60,40)); - centroids.push_back(Point(-60,-40)); - centroids.push_back(Point(00,-40)); - centroids.push_back(Point(00,40)); - centroids.push_back(Point(-30,-40)); - centroids.push_back(Point(30,40)); - centroids.push_back(Point(-30,40)); - centroids.push_back(Point(30,-40)); - centroids.push_back(Point(60,00)); - centroids.push_back(Point(-70,00)); - centroids.push_back(Point(-60,-20)); - - - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* r = _building->GetRoom(i); - string caption = r->GetCaption(); - - //skip the virtual room containing the complete geometry - if(r->GetCaption()=="outside") continue; - if(r->GetZPos()>6) continue; - const Point& centroid0 = Point(0,0); - - for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { - SubRoom* s = r->GetSubRoom(k); - - //walls - const vector<Wall>& walls = s->GetAllWalls(); - - for (unsigned w = 0; w < walls.size(); w++) { - - bool skip=false; - for(unsigned int i=0;i<centroids.size();i++){ - if(walls[w].DistTo(centroids[i])<25) skip=true; - } - if(skip==true) continue; - - //first attempt - Point P0 = walls[w].GetPoint1(); - Point P1 = walls[w].GetPoint2(); - Point D0 = P1 - P0; - Point D1 = centroid0-P0; - if (D0.Det(D1) < 0) { - envelope.push_back(Line(P0, P1)); - }else{ - envelope.push_back(Line(P1, P0)); - } - } - - - const vector<Transition*>& transitions = s->GetAllTransitions(); - for (unsigned t = 0; t < transitions.size(); t++) { - - if(transitions[t]->GetSubRoom2() != NULL) continue; - - bool skip=false; - for(unsigned int i=0;i<centroids.size();i++){ - if(transitions[t]->DistTo(centroids[i])<25) skip=true; - } - if(skip==true) continue; - - //first attempt - Point P0 = transitions[t]->GetPoint1(); - Point P1 = transitions[t]->GetPoint2(); - Point D0 = P1 - P0; - Point D1 = centroid0-P0; - if (D0.Det(D1) < 0) { - envelope.push_back(Line(P0, P1)); - }else{ - envelope.push_back(Line(P1, P0)); - } - } - } - } - - - //link those vertices - vector<Point> Hull; - Hull.push_back(envelope[envelope.size()-1].GetPoint1()); - Hull.push_back(envelope[envelope.size()-1].GetPoint2()); - envelope.pop_back(); - - while(envelope.empty()==false){ - for(unsigned int i=0;i<envelope.size();i++){ - if(envelope[i].GetPoint1()==Hull[Hull.size()-1]){ - Hull.push_back(envelope[i].GetPoint2()); - envelope.erase(envelope.begin()+i); - }else if(envelope[i].GetPoint2()==Hull[Hull.size()-1]) - { - Hull.push_back(envelope[i].GetPoint1()); - envelope.erase(envelope.begin()+i); - } - } - } - - //eject the last point which is a duplicate. - Hull.pop_back(); - - //the surrounding room - vector<Point> Hull2=_building->GetRoom("outside")->GetSubRoom(0)->GetPolygon(); +void NavMesh::Finalize() +{ + + Log->Write("INFO:\tFinalizing the mesh"); + + // WriteToFileTraVisTo("arena_envelope.xml",envelope); + //collect all possible vertices that form that envelope + + vector<Line> envelope; + vector<Point> centroids; + //centroids.push_back(Point(0,0)); + centroids.push_back(Point(60,40)); + centroids.push_back(Point(60,-40)); + centroids.push_back(Point(-60,40)); + centroids.push_back(Point(-60,-40)); + centroids.push_back(Point(00,-40)); + centroids.push_back(Point(00,40)); + centroids.push_back(Point(-30,-40)); + centroids.push_back(Point(30,40)); + centroids.push_back(Point(-30,40)); + centroids.push_back(Point(30,-40)); + centroids.push_back(Point(60,00)); + centroids.push_back(Point(-70,00)); + centroids.push_back(Point(-60,-20)); + + + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* r = _building->GetRoom(i); + string caption = r->GetCaption(); + + //skip the virtual room containing the complete geometry + if(r->GetCaption()=="outside") continue; + if(r->GetZPos()>6) continue; + const Point& centroid0 = Point(0,0); + + for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { + SubRoom* s = r->GetSubRoom(k); + + //walls + const vector<Wall>& walls = s->GetAllWalls(); + + for (unsigned w = 0; w < walls.size(); w++) { + + bool skip=false; + for(unsigned int i=0; i<centroids.size(); i++) { + if(walls[w].DistTo(centroids[i])<25) skip=true; + } + if(skip==true) continue; + + //first attempt + Point P0 = walls[w].GetPoint1(); + Point P1 = walls[w].GetPoint2(); + Point D0 = P1 - P0; + Point D1 = centroid0-P0; + if (D0.Det(D1) < 0) { + envelope.push_back(Line(P0, P1)); + } else { + envelope.push_back(Line(P1, P0)); + } + } + + + const vector<Transition*>& transitions = s->GetAllTransitions(); + for (unsigned t = 0; t < transitions.size(); t++) { + + if(transitions[t]->GetSubRoom2() != NULL) continue; + + bool skip=false; + for(unsigned int i=0; i<centroids.size(); i++) { + if(transitions[t]->DistTo(centroids[i])<25) skip=true; + } + if(skip==true) continue; + + //first attempt + Point P0 = transitions[t]->GetPoint1(); + Point P1 = transitions[t]->GetPoint2(); + Point D0 = P1 - P0; + Point D1 = centroid0-P0; + if (D0.Det(D1) < 0) { + envelope.push_back(Line(P0, P1)); + } else { + envelope.push_back(Line(P1, P0)); + } + } + } + } + + + //link those vertices + vector<Point> Hull; + Hull.push_back(envelope[envelope.size()-1].GetPoint1()); + Hull.push_back(envelope[envelope.size()-1].GetPoint2()); + envelope.pop_back(); + + while(envelope.empty()==false) { + for(unsigned int i=0; i<envelope.size(); i++) { + if(envelope[i].GetPoint1()==Hull[Hull.size()-1]) { + Hull.push_back(envelope[i].GetPoint2()); + envelope.erase(envelope.begin()+i); + } else if(envelope[i].GetPoint2()==Hull[Hull.size()-1]) { + Hull.push_back(envelope[i].GetPoint1()); + envelope.erase(envelope.begin()+i); + } + } + } + + //eject the last point which is a duplicate. + Hull.pop_back(); + + //the surrounding room + vector<Point> Hull2=_building->GetRoom("outside")->GetSubRoom(0)->GetPolygon(); #ifdef _CGAL - //print for some check - //WriteToFileTraVisTo("arena_envelope.xml",Hull); - //exit(0); - //now check the polygon with holes. - - // { - // ofstream myfile ("mypoints.pts"); - // if (myfile.is_open()) - // { - // //quick testing - // for(unsigned int i=0;i<Hull2.size();i++){ - // myfile <<"P "<<Hull2[i].pX <<" "<<Hull2[i].pY<<endl; - // } - // myfile <<"H "<<Hull[0].pX <<" "<<Hull[0].pY<<endl; - // for(unsigned int i=1;i<Hull.size();i++){ - // myfile <<"P "<<Hull[i].pX <<" "<<Hull[i].pY<<endl; - // } - // } - // - // } - //WriteToFileTraVisTo("arena_envelope.xml",Hull); - - //perform some tests using CGAL - - //first polygon - Polygon_2 polygon2; - Polygon_2 holesP[1]; - - - for(unsigned int i=0;i<Hull.size();i++){ - holesP[0].push_back(Point_2(Hull[i]._x,Hull[i]._y)); - } - - for(unsigned int i=0;i<Hull2.size();i++){ - polygon2.push_back(Point_2(Hull2[i]._x,Hull2[i]._y)); - } - - if(holesP[0].is_clockwise_oriented())holesP[0].reverse_orientation(); - if(polygon2.is_clockwise_oriented())polygon2.reverse_orientation(); - - assert(holesP[0].is_counterclockwise_oriented()); - assert(polygon2.is_counterclockwise_oriented()); - assert(holesP[0].is_simple()); - assert(polygon2.is_simple()); + //print for some check + //WriteToFileTraVisTo("arena_envelope.xml",Hull); + //exit(0); + //now check the polygon with holes. + + // { + // ofstream myfile ("mypoints.pts"); + // if (myfile.is_open()) + // { + // //quick testing + // for(unsigned int i=0;i<Hull2.size();i++){ + // myfile <<"P "<<Hull2[i].pX <<" "<<Hull2[i].pY<<endl; + // } + // myfile <<"H "<<Hull[0].pX <<" "<<Hull[0].pY<<endl; + // for(unsigned int i=1;i<Hull.size();i++){ + // myfile <<"P "<<Hull[i].pX <<" "<<Hull[i].pY<<endl; + // } + // } + // + // } + //WriteToFileTraVisTo("arena_envelope.xml",Hull); + + //perform some tests using CGAL + + //first polygon + Polygon_2 polygon2; + Polygon_2 holesP[1]; + + + for(unsigned int i=0; i<Hull.size(); i++) { + holesP[0].push_back(Point_2(Hull[i]._x,Hull[i]._y)); + } + + for(unsigned int i=0; i<Hull2.size(); i++) { + polygon2.push_back(Point_2(Hull2[i]._x,Hull2[i]._y)); + } + + if(holesP[0].is_clockwise_oriented())holesP[0].reverse_orientation(); + if(polygon2.is_clockwise_oriented())polygon2.reverse_orientation(); + + assert(holesP[0].is_counterclockwise_oriented()); + assert(polygon2.is_counterclockwise_oriented()); + assert(holesP[0].is_simple()); + assert(polygon2.is_simple()); #endif //_CGAL - Log->Write("INFO:\tPerforming final triangulation with the outside!"); - - DTriangulation* tri= new DTriangulation(); - tri->SetOuterPolygone(Hull); - tri->AddHole(Hull2); - tri->Triangulate(); - vector<p2t::Triangle*> triangles=tri->GetTriangles(); - - // CGAL::Geomview_stream gv(CGAL::Bbox_3(-100, -100, -100, 100, 100, 100)); - // gv.set_line_width(4); - // gv.set_trace(true); - // gv.set_bg_color(CGAL::Color(0, 200, 200)); - // // gv.clear(); - // - // // use different colors, and put a few sleeps/clear. - // gv << CGAL::BLUE; - // gv.set_wired(true); - - for(unsigned int t=0;t<triangles.size();t++){ - p2t::Triangle* tr =triangles[t]; - - // Point_2 P0 = Point_2 (tr->GetPoint(0)->x,tr->GetPoint(0)->y); - // Point_2 P1 = Point_2 (tr->GetPoint(1)->x,tr->GetPoint(1)->y); - // Point_2 P2 = Point_2 (tr->GetPoint(2)->x,tr->GetPoint(2)->y); - // gv << Segment_2(P0,P1); - // gv << Segment_2(P1,P2); - // gv << Segment_2(P0,P2); - - Point P0 = Point (tr->GetPoint(0)->x,tr->GetPoint(0)->y); - Point P1 = Point (tr->GetPoint(1)->x,tr->GetPoint(1)->y); - Point P2 = Point (tr->GetPoint(2)->x,tr->GetPoint(2)->y); - - //create the new nodes - - JNode* new_node = new JNode(); - new_node->pGroup = "outside"; - //to get a correct ID - AddNode(new_node); - new_nodes.push_back(new_node); - new_node->pCentroid= (P0+P1+P2)*(1.0/3); - - new_node->pNormalVec[0]=0.0; - new_node->pNormalVec[1]=0.0; - new_node->pNormalVec[2]=0.0; - - // Points are by default counterclockwise - new_node->pHull.push_back(*(GetVertex(P0))); - new_node->pHull.push_back(*(GetVertex(P1))); - new_node->pHull.push_back(*(GetVertex(P2))); - - for (int index=0;index<3;index++){ - - Point P0 = Point (tr->GetPoint(index%3)->x,tr->GetPoint(index%3)->y); - Point P1 = Point (tr->GetPoint((index+1)%3)->x,tr->GetPoint((index+1)%3)->y); - - int edge_id=IsPortal(P0,P1); - if(edge_id != -1){ - //if(IsElementInVector(new_node->pPortals,edge_id)==false) - new_node->pPortals.push_back(edge_id); - - //invalidate any previous information - // they will be set later - JEdge* e = _edges[edge_id]; - e->pNode0=-1; - e->pNode1=-1; - } - - int obstacle_id=IsObstacle(P0,P1); - if(obstacle_id != -1){ - //std::cerr<<"Error: the convexification has created an JObstacle"<<endl; - //if(IsElementInVector(new_node->pObstacles,obstacle_id)==false) - new_node->pObstacles.push_back(obstacle_id); - - // FIXME 23 - //pObst[obstacle_id]->pNode0=new_node->id; - } - - // this portal was newly created - if ((obstacle_id==-1) && (edge_id==-1)){ - - JEdge* e= new JEdge(); - e->pEnd=*GetVertex(P1); - e->pStart= *GetVertex(P0); - AddEdge(e); - - //invalidate any previous information - // they will be set later - e->pNode0=-1; - e->pNode1=-1; - // caution: the ID is automatically assigned in the AddEdge method - //if(IsElementInVector(new_node->pPortals,edge_id)==false) - new_node->pPortals.push_back(e->id); - - } - } - } - - UpdateEdges(); - delete tri; - - Log->Write("INFO:\t...Done!"); + Log->Write("INFO:\tPerforming final triangulation with the outside!"); + + DTriangulation* tri= new DTriangulation(); + tri->SetOuterPolygone(Hull); + tri->AddHole(Hull2); + tri->Triangulate(); + vector<p2t::Triangle*> triangles=tri->GetTriangles(); + + // CGAL::Geomview_stream gv(CGAL::Bbox_3(-100, -100, -100, 100, 100, 100)); + // gv.set_line_width(4); + // gv.set_trace(true); + // gv.set_bg_color(CGAL::Color(0, 200, 200)); + // // gv.clear(); + // + // // use different colors, and put a few sleeps/clear. + // gv << CGAL::BLUE; + // gv.set_wired(true); + + for(unsigned int t=0; t<triangles.size(); t++) { + p2t::Triangle* tr =triangles[t]; + + // Point_2 P0 = Point_2 (tr->GetPoint(0)->x,tr->GetPoint(0)->y); + // Point_2 P1 = Point_2 (tr->GetPoint(1)->x,tr->GetPoint(1)->y); + // Point_2 P2 = Point_2 (tr->GetPoint(2)->x,tr->GetPoint(2)->y); + // gv << Segment_2(P0,P1); + // gv << Segment_2(P1,P2); + // gv << Segment_2(P0,P2); + + Point P0 = Point (tr->GetPoint(0)->x,tr->GetPoint(0)->y); + Point P1 = Point (tr->GetPoint(1)->x,tr->GetPoint(1)->y); + Point P2 = Point (tr->GetPoint(2)->x,tr->GetPoint(2)->y); + + //create the new nodes + + JNode* new_node = new JNode(); + new_node->pGroup = "outside"; + //to get a correct ID + AddNode(new_node); + new_nodes.push_back(new_node); + new_node->pCentroid= (P0+P1+P2)*(1.0/3); + + new_node->pNormalVec[0]=0.0; + new_node->pNormalVec[1]=0.0; + new_node->pNormalVec[2]=0.0; + + // Points are by default counterclockwise + new_node->pHull.push_back(*(GetVertex(P0))); + new_node->pHull.push_back(*(GetVertex(P1))); + new_node->pHull.push_back(*(GetVertex(P2))); + + for (int index=0; index<3; index++) { + + Point P0 = Point (tr->GetPoint(index%3)->x,tr->GetPoint(index%3)->y); + Point P1 = Point (tr->GetPoint((index+1)%3)->x,tr->GetPoint((index+1)%3)->y); + + int edge_id=IsPortal(P0,P1); + if(edge_id != -1) { + //if(IsElementInVector(new_node->pPortals,edge_id)==false) + new_node->pPortals.push_back(edge_id); + + //invalidate any previous information + // they will be set later + JEdge* e = _edges[edge_id]; + e->pNode0=-1; + e->pNode1=-1; + } + + int obstacle_id=IsObstacle(P0,P1); + if(obstacle_id != -1) { + //std::cerr<<"Error: the convexification has created an JObstacle"<<endl; + //if(IsElementInVector(new_node->pObstacles,obstacle_id)==false) + new_node->pObstacles.push_back(obstacle_id); + + // FIXME 23 + //pObst[obstacle_id]->pNode0=new_node->id; + } + + // this portal was newly created + if ((obstacle_id==-1) && (edge_id==-1)) { + + JEdge* e= new JEdge(); + e->pEnd=*GetVertex(P1); + e->pStart= *GetVertex(P0); + AddEdge(e); + + //invalidate any previous information + // they will be set later + e->pNode0=-1; + e->pNode1=-1; + // caution: the ID is automatically assigned in the AddEdge method + //if(IsElementInVector(new_node->pPortals,edge_id)==false) + new_node->pPortals.push_back(e->id); + + } + } + } + + UpdateEdges(); + delete tri; + + Log->Write("INFO:\t...Done!"); } -void NavMesh::Triangulate(SubRoom* sub) { +void NavMesh::Triangulate(SubRoom* sub) +{ - //vertices - vector<Point> outerHull= sub->GetPolygon(); + //vertices + vector<Point> outerHull= sub->GetPolygon(); - // Vertices - for (unsigned int p = 0; p < outerHull.size(); p++) { - JVertex* v = new JVertex(); - v->pPos= outerHull[p]; - if(AddVertex(v)==-1) { - delete v; - } - } + // Vertices + for (unsigned int p = 0; p < outerHull.size(); p++) { + JVertex* v = new JVertex(); + v->pPos= outerHull[p]; + if(AddVertex(v)==-1) { + delete v; + } + } - vector<vector<Point> >holes; - const vector<Obstacle*>& obstacles= sub->GetAllObstacles(); + vector<vector<Point> >holes; + const vector<Obstacle*>& obstacles= sub->GetAllObstacles(); - for(unsigned int p=0;p<obstacles.size();p++){ - holes.push_back(obstacles[p]->GetPolygon()); - } + for(unsigned int p=0; p<obstacles.size(); p++) { + holes.push_back(obstacles[p]->GetPolygon()); + } #ifdef _CGAL - //perform some checks - Polygon_2 polygon; - Polygon_2 holesP[holes.size()]; - - for(unsigned int i=0;i<outerHull.size();i++){ - polygon.push_back(Point_2(outerHull[i]._x,outerHull[i]._y)); - } - assert(polygon.is_simple()); - if(polygon.is_clockwise_oriented()){ - std::reverse(outerHull.begin(), outerHull.end()); - polygon.reverse_orientation(); - } - assert(polygon.is_counterclockwise_oriented()); - - - for(unsigned int i=0;i<holes.size();i++){ - for(unsigned int j=0;j<holes[i].size();j++){ - holesP[i].push_back(Point_2(holes[j][i]._x,holes[j][i]._y)); - } - - if(holesP[i].is_clockwise_oriented()) { - holesP[i].reverse_orientation(); - std::reverse(holes[i].begin(), holes[i].end()); - } - assert(holesP[i].is_counterclockwise_oriented()); - assert(holesP[i].is_simple()); - } + //perform some checks + Polygon_2 polygon; + Polygon_2 holesP[holes.size()]; + + for(unsigned int i=0; i<outerHull.size(); i++) { + polygon.push_back(Point_2(outerHull[i]._x,outerHull[i]._y)); + } + assert(polygon.is_simple()); + if(polygon.is_clockwise_oriented()) { + std::reverse(outerHull.begin(), outerHull.end()); + polygon.reverse_orientation(); + } + assert(polygon.is_counterclockwise_oriented()); + + + for(unsigned int i=0; i<holes.size(); i++) { + for(unsigned int j=0; j<holes[i].size(); j++) { + holesP[i].push_back(Point_2(holes[j][i]._x,holes[j][i]._y)); + } + + if(holesP[i].is_clockwise_oriented()) { + holesP[i].reverse_orientation(); + std::reverse(holes[i].begin(), holes[i].end()); + } + assert(holesP[i].is_counterclockwise_oriented()); + assert(holesP[i].is_simple()); + } #endif // _CGAL - DTriangulation* tri= new DTriangulation(); - tri->SetOuterPolygone(outerHull); + DTriangulation* tri= new DTriangulation(); + tri->SetOuterPolygone(outerHull); - //add the holes - for(unsigned int i=0;i<holes.size();i++){ - tri->AddHole(holes[i]); - } + //add the holes + for(unsigned int i=0; i<holes.size(); i++) { + tri->AddHole(holes[i]); + } - tri->Triangulate(); + tri->Triangulate(); - vector<p2t::Triangle*> triangles=tri->GetTriangles(); + vector<p2t::Triangle*> triangles=tri->GetTriangles(); - for(unsigned int t=0;t<triangles.size();t++) - { - p2t::Triangle* tr =triangles[t]; + for(unsigned int t=0; t<triangles.size(); t++) { + p2t::Triangle* tr =triangles[t]; - Point P0 = Point (tr->GetPoint(0)->x,tr->GetPoint(0)->y); - Point P1 = Point (tr->GetPoint(1)->x,tr->GetPoint(1)->y); - Point P2 = Point (tr->GetPoint(2)->x,tr->GetPoint(2)->y); + Point P0 = Point (tr->GetPoint(0)->x,tr->GetPoint(0)->y); + Point P1 = Point (tr->GetPoint(1)->x,tr->GetPoint(1)->y); + Point P2 = Point (tr->GetPoint(2)->x,tr->GetPoint(2)->y); - //create the new nodes - JNode* new_node = new JNode(); - new_node->pGroup = "outside"; - //to get a correct ID - AddNode(new_node); - new_nodes.push_back(new_node); - new_node->pCentroid= (P0+P1+P2)*(1.0/3); + //create the new nodes + JNode* new_node = new JNode(); + new_node->pGroup = "outside"; + //to get a correct ID + AddNode(new_node); + new_nodes.push_back(new_node); + new_node->pCentroid= (P0+P1+P2)*(1.0/3); - new_node->pNormalVec[0]=0; - new_node->pNormalVec[1]=0; - new_node->pNormalVec[2]=_building->GetRoom(sub->GetRoomID())->GetZPos(); + new_node->pNormalVec[0]=0; + new_node->pNormalVec[1]=0; + new_node->pNormalVec[2]=_building->GetRoom(sub->GetRoomID())->GetZPos(); - // Points are by default counterclockwise - new_node->pHull.push_back(*(GetVertex(P0))); - new_node->pHull.push_back(*(GetVertex(P1))); - new_node->pHull.push_back(*(GetVertex(P2))); + // Points are by default counterclockwise + new_node->pHull.push_back(*(GetVertex(P0))); + new_node->pHull.push_back(*(GetVertex(P1))); + new_node->pHull.push_back(*(GetVertex(P2))); - for (int index=0;index<3;index++){ + for (int index=0; index<3; index++) { - Point P0 = Point (tr->GetPoint(index%3)->x,tr->GetPoint(index%3)->y); - Point P1 = Point (tr->GetPoint((index+1)%3)->x,tr->GetPoint((index+1)%3)->y); + Point P0 = Point (tr->GetPoint(index%3)->x,tr->GetPoint(index%3)->y); + Point P1 = Point (tr->GetPoint((index+1)%3)->x,tr->GetPoint((index+1)%3)->y); - int edge_id=IsPortal(P0,P1); - if(edge_id != -1){ - new_node->pPortals.push_back(edge_id); - JEdge* e = _edges[edge_id]; + int edge_id=IsPortal(P0,P1); + if(edge_id != -1) { + new_node->pPortals.push_back(edge_id); + JEdge* e = _edges[edge_id]; - // invalidate the node - e->pNode0=-1; - e->pNode1=-1; + // invalidate the node + e->pNode0=-1; + e->pNode1=-1; - } + } - int obstacle_id=IsObstacle(P0,P1); - if(obstacle_id != -1){ - //std::cerr<<"Error: the convexification has created an JObstacle"<<endl; - new_node->pObstacles.push_back(obstacle_id); - _obst[obstacle_id]->pNode0=new_node->id; - } + int obstacle_id=IsObstacle(P0,P1); + if(obstacle_id != -1) { + //std::cerr<<"Error: the convexification has created an JObstacle"<<endl; + new_node->pObstacles.push_back(obstacle_id); + _obst[obstacle_id]->pNode0=new_node->id; + } - // this portal was newly created - if ((obstacle_id==-1) && (edge_id==-1)){ + // this portal was newly created + if ((obstacle_id==-1) && (edge_id==-1)) { - JEdge* e= new JEdge(); - e->pEnd=*GetVertex(P1); - e->pStart= *GetVertex(P0); - AddEdge(e); + JEdge* e= new JEdge(); + e->pEnd=*GetVertex(P1); + e->pStart= *GetVertex(P0); + AddEdge(e); - // invalidate the node - e->pNode0=-1; - e->pNode1=-1; + // invalidate the node + e->pNode0=-1; + e->pNode1=-1; - // caution: the ID is automatically assigned in the AddEdge method - new_node->pPortals.push_back(e->id); - } - } - } + // caution: the ID is automatically assigned in the AddEdge method + new_node->pPortals.push_back(e->id); + } + } + } - UpdateEdges(); + UpdateEdges(); } -void NavMesh::Triangulate(JNode* node) { - - //if(node->IsConvex()) return; - - vector<Point> outerHull; - - for(unsigned int h=0;h<node->pHull.size();h++){ - outerHull.push_back(node->pHull[h].pPos); - } +void NavMesh::Triangulate(JNode* node) +{ + + //if(node->IsConvex()) return; + + vector<Point> outerHull; + + for(unsigned int h=0; h<node->pHull.size(); h++) { + outerHull.push_back(node->pHull[h].pPos); + } + + DTriangulation* tri= new DTriangulation(); + tri->SetOuterPolygone(outerHull); + + //treating obstacles as holes + int rID=map_node_to_subroom[node->id].first; + int sID=map_node_to_subroom[node->id].second; + SubRoom* sub = _building->GetRoom(rID)->GetSubRoom(sID); + + const vector<Obstacle*> obstacles=sub->GetAllObstacles(); + + for( unsigned int a = 0; a < obstacles.size(); a++) { + + Obstacle* obst= obstacles[a]; + + const vector<Point>& pol =obst->GetPolygon(); + // Vertices + for (unsigned int p = 0; p < pol.size(); p++) { + JVertex* v = new JVertex(); + v->pPos= pol[p]; + if(AddVertex(v)==-1) { + delete v; + } + } + + //obstacles + const vector<Wall>& walls = obst->GetAllWalls(); + for (unsigned w = 0; w < walls.size(); w++) { + const Point& centroid0 = obst->GetCentroid(); + //int node0 = s->GetUID(); + + JObstacle* o= new JObstacle(); + o->pNode0=node->id; + o->pNextObst=-1; + + //first attempt + Point P0 = walls[w].GetPoint1(); + Point P1 = walls[w].GetPoint2(); + Point D0 = P1 - P0; + Point D1 = centroid0-P0; + if (D0.Det(D1) < 0) { + //o->pDisp=D0; + o->pEnd=*GetVertex(P1); + o->pStart= *GetVertex(P0); + + } else { + o->pStart= *GetVertex(P1); + //o->pDisp=Point(0,0)-D0; + o->pEnd=*GetVertex(P0); + } + + if (AddObst(o)==-1) { + // the JEdge is already there + o->id=IsObstacle(o->pStart.pPos, o->pEnd.pPos); + delete o; + } + //node->pObstacles.push_back(o->id); + } + tri->AddHole(pol); + //cout<<"obstacle in sub"<<endl; + //exit(0); + } + + //tri->AddHole(Hull2); + tri->Triangulate(); + vector<p2t::Triangle*> triangles=tri->GetTriangles(); + + for(unsigned int t=0; t<triangles.size(); t++) { + p2t::Triangle* tr =triangles[t]; + + Point P0 = Point (tr->GetPoint(0)->x,tr->GetPoint(0)->y); + Point P1 = Point (tr->GetPoint(1)->x,tr->GetPoint(1)->y); + Point P2 = Point (tr->GetPoint(2)->x,tr->GetPoint(2)->y); + + //create the new nodes + JNode* new_node = new JNode(); + new_node->pGroup = node->pGroup; + //to get a correct ID + AddNode(new_node); + + assert(new_node->id!=-1); + + new_nodes.push_back(new_node); + new_node->pCentroid= (P0+P1+P2)*(1.0/3); + + new_node->pNormalVec[0]=node->pNormalVec[0]; + new_node->pNormalVec[1]=node->pNormalVec[1]; + new_node->pNormalVec[2]=node->pNormalVec[2]; + + // Points are by default counterclockwise + new_node->pHull.push_back(*(GetVertex(P0))); + new_node->pHull.push_back(*(GetVertex(P1))); + new_node->pHull.push_back(*(GetVertex(P2))); + + + for (int index=0; index<3; index++) { + + Point P0 = Point (tr->GetPoint(index%3)->x,tr->GetPoint(index%3)->y); + Point P1 = Point (tr->GetPoint((index+1)%3)->x,tr->GetPoint((index+1)%3)->y); + + int edge_id=IsPortal(P0,P1); + if(edge_id != -1) { + new_node->pPortals.push_back(edge_id); + JEdge* e = _edges[edge_id]; + + //invalidate the node + e->pNode0=-1; + e->pNode1=-1; + } + + int obstacle_id=IsObstacle(P0,P1); + if(obstacle_id != -1) { + //std::cerr<<"Error: the convexification has created an JObstacle"<<endl; + new_node->pObstacles.push_back(obstacle_id); + // pObst[obstacle_id]->pNode0=new_node->id; + _obst[obstacle_id]->pNode0=-1; + } + + // this portal was newly created + if ((obstacle_id==-1) && (edge_id==-1)) { + + JEdge* e= new JEdge(); + e->pEnd=*GetVertex(P1); + e->pStart= *GetVertex(P0); + AddEdge(e); + + //invalidate the node + e->pNode0=-1; + e->pNode1=-1; + + // caution: the ID is automatically assigned in the AddEdge method + new_node->pPortals.push_back(e->id); + } + } + } + + //return; //fixme + { + // now post processing the newly created nodes + assert (node->id != (_nodes.size() -1) && "Trying to remove the last node !"); + JNode* new_node = _nodes.back(); + _nodes.pop_back(); + + //making the transformation + + for(unsigned int i=0; i<new_node->pObstacles.size(); i++) { + _obst[new_node->pObstacles[i]]->pNode0=node->id; + } + + + for(unsigned int i=0; i<new_node->pPortals.size(); i++) { + + if(_edges[new_node->pPortals[i]]->pNode0==new_node->id) { + _edges[new_node->pPortals[i]]->pNode0=node->id; + } else { + _edges[new_node->pPortals[i]]->pNode1=node->id; + } + } - DTriangulation* tri= new DTriangulation(); - tri->SetOuterPolygone(outerHull); - - //treating obstacles as holes - int rID=map_node_to_subroom[node->id].first; - int sID=map_node_to_subroom[node->id].second; - SubRoom* sub = _building->GetRoom(rID)->GetSubRoom(sID); - - const vector<Obstacle*> obstacles=sub->GetAllObstacles(); - - for( unsigned int a = 0; a < obstacles.size(); a++){ - - Obstacle* obst= obstacles[a]; - - const vector<Point>& pol =obst->GetPolygon(); - // Vertices - for (unsigned int p = 0; p < pol.size(); p++) { - JVertex* v = new JVertex(); - v->pPos= pol[p]; - if(AddVertex(v)==-1) { - delete v; - } - } - - //obstacles - const vector<Wall>& walls = obst->GetAllWalls(); - for (unsigned w = 0; w < walls.size(); w++) { - const Point& centroid0 = obst->GetCentroid(); - //int node0 = s->GetUID(); - - JObstacle* o= new JObstacle(); - o->pNode0=node->id; - o->pNextObst=-1; - - //first attempt - Point P0 = walls[w].GetPoint1(); - Point P1 = walls[w].GetPoint2(); - Point D0 = P1 - P0; - Point D1 = centroid0-P0; - if (D0.Det(D1) < 0) { - //o->pDisp=D0; - o->pEnd=*GetVertex(P1); - o->pStart= *GetVertex(P0); - - }else{ - o->pStart= *GetVertex(P1); - //o->pDisp=Point(0,0)-D0; - o->pEnd=*GetVertex(P0); - } - - if (AddObst(o)==-1) { - // the JEdge is already there - o->id=IsObstacle(o->pStart.pPos, o->pEnd.pPos); - delete o; - } - //node->pObstacles.push_back(o->id); - } - tri->AddHole(pol); - //cout<<"obstacle in sub"<<endl; - //exit(0); - } - - //tri->AddHole(Hull2); - tri->Triangulate(); - vector<p2t::Triangle*> triangles=tri->GetTriangles(); - - for(unsigned int t=0;t<triangles.size();t++){ - p2t::Triangle* tr =triangles[t]; - - Point P0 = Point (tr->GetPoint(0)->x,tr->GetPoint(0)->y); - Point P1 = Point (tr->GetPoint(1)->x,tr->GetPoint(1)->y); - Point P2 = Point (tr->GetPoint(2)->x,tr->GetPoint(2)->y); - - //create the new nodes - JNode* new_node = new JNode(); - new_node->pGroup = node->pGroup; - //to get a correct ID - AddNode(new_node); - - assert(new_node->id!=-1); - - new_nodes.push_back(new_node); - new_node->pCentroid= (P0+P1+P2)*(1.0/3); - - new_node->pNormalVec[0]=node->pNormalVec[0]; - new_node->pNormalVec[1]=node->pNormalVec[1]; - new_node->pNormalVec[2]=node->pNormalVec[2]; - - // Points are by default counterclockwise - new_node->pHull.push_back(*(GetVertex(P0))); - new_node->pHull.push_back(*(GetVertex(P1))); - new_node->pHull.push_back(*(GetVertex(P2))); - - - for (int index=0;index<3;index++){ - - Point P0 = Point (tr->GetPoint(index%3)->x,tr->GetPoint(index%3)->y); - Point P1 = Point (tr->GetPoint((index+1)%3)->x,tr->GetPoint((index+1)%3)->y); - - int edge_id=IsPortal(P0,P1); - if(edge_id != -1){ - new_node->pPortals.push_back(edge_id); - JEdge* e = _edges[edge_id]; - - //invalidate the node - e->pNode0=-1; - e->pNode1=-1; - } - - int obstacle_id=IsObstacle(P0,P1); - if(obstacle_id != -1){ - //std::cerr<<"Error: the convexification has created an JObstacle"<<endl; - new_node->pObstacles.push_back(obstacle_id); - // pObst[obstacle_id]->pNode0=new_node->id; - _obst[obstacle_id]->pNode0=-1; - } - - // this portal was newly created - if ((obstacle_id==-1) && (edge_id==-1)){ - - JEdge* e= new JEdge(); - e->pEnd=*GetVertex(P1); - e->pStart= *GetVertex(P0); - AddEdge(e); - - //invalidate the node - e->pNode0=-1; - e->pNode1=-1; - - // caution: the ID is automatically assigned in the AddEdge method - new_node->pPortals.push_back(e->id); - } - } - } - - //return; //fixme - { - // now post processing the newly created nodes - assert (node->id != (_nodes.size() -1) && "Trying to remove the last node !"); - JNode* new_node = _nodes.back(); - _nodes.pop_back(); - - //making the transformation - - for(unsigned int i=0;i<new_node->pObstacles.size();i++){ - _obst[new_node->pObstacles[i]]->pNode0=node->id; - } - - - for(unsigned int i=0;i<new_node->pPortals.size();i++){ - - if(_edges[new_node->pPortals[i]]->pNode0==new_node->id){ - _edges[new_node->pPortals[i]]->pNode0=node->id; - } - else - { - _edges[new_node->pPortals[i]]->pNode1=node->id; - } - } + new_node->id=node->id; + _nodes[node->id]=new_node; - new_node->id=node->id; - _nodes[node->id]=new_node; + delete node; + } - delete node; - } + UpdateEdges(); + UpdateObstacles(); - UpdateEdges(); - UpdateObstacles(); - - delete tri; + delete tri; } -int NavMesh::IsObstacle(Point& p1, Point& p2) { +int NavMesh::IsObstacle(Point& p1, Point& p2) +{ - for(unsigned int i=0;i<_obst.size();i++){ - JObstacle* obst=_obst[i]; + for(unsigned int i=0; i<_obst.size(); i++) { + JObstacle* obst=_obst[i]; - if( (obst->pStart.pPos==p1) && (obst->pEnd.pPos==p2)){ - return obst->id; - } + if( (obst->pStart.pPos==p1) && (obst->pEnd.pPos==p2)) { + return obst->id; + } - if( (obst->pStart.pPos==p2) && (obst->pEnd.pPos==p1)){ - return obst->id; - } - } + if( (obst->pStart.pPos==p2) && (obst->pEnd.pPos==p1)) { + return obst->id; + } + } - return -1; + return -1; } -void NavMesh::WriteScenario() { - WriteBehavior(); - WriteViewer(); - WriteStartPositions(); +void NavMesh::WriteScenario() +{ + WriteBehavior(); + WriteViewer(); + WriteStartPositions(); } -void NavMesh::WriteBehavior() { - string filename="../pedunc/examples/stadium/arenaB.xml"; - ofstream file(filename.c_str()); - file.precision(2); - file<<fixed; - - if(file.is_open()==false){ - cout <<"could not open the file: "<<filename<<endl; - return; - } - - file<< "<?xml version=\"1.0\"?>"<<endl; - file<< "\t<Population>"<<endl; - - - int goalsetid=0; - //Write the goal set outside - { - file<< "\t\t<GoalSet id=\""<<goalsetid++<<"\" description=\"outside\">"<<endl; - - vector<Point> goals=_building->GetRoom("outside")->GetSubRoom(0)->GetPolygon(); - for(unsigned int g=0;g<goals.size();g++){ - double factor=(10.0/(goals[g].Norm())-1); - file<< "\t\t\t<Goal type=\"point\" id=\""<<g<<"\" x=\""<< factor*goals[g]._x<<"\" y=\""<<factor*goals[g]._y<<"\"/>"<<endl; - } - file<< "\t\t</GoalSet>"<<endl; - } - - - //write the goal set tunnel - { - file<< "\t\t<GoalSet id=\""<<goalsetid++<<"\" description=\"tunnel\">"<<endl; - - for (map<int, Transition*>::const_iterator itr = _building->GetAllTransitions().begin(); - itr != _building->GetAllTransitions().end(); ++itr) { - - int door=itr->first; - //int door = itr->second->GetUniqueID(); - Transition* cross = itr->second; - const Point& centre = cross->GetCentre(); - - if((cross->Length()<2.6) && (cross->Length()>2.4)) - - file<< "\t\t\t<Goal type=\"point\" id=\""<<door<<"\" x=\""<< centre._x<<"\" y=\""<<centre._y<<"\"/>"<<endl; - } - file<< "\t\t</GoalSet>"<<endl; - } - - //write the goal set promenade - - file<< "\t\t<Behavior class=\"1\">"<<endl; - file<< "\t\t\t<Property name=\"prefSpeed\" type=\"float\" dist=\"c\" value=\"1.3\" />"<<endl; - file<< "\t\t\t<Property type=\"2D\" name=\"stride\" dist=\"c\" factor_value=\"100.57\" buffer_value=\"0.0\" />"<<endl; - file<< ""<<endl; - file<< "\t\t\t<State name=\"Walk1\" speedPolicy=\"min\" final=\"0\" >"<<endl; - file<< "<!--"<<endl; - file<< "<NavMeshGoal goalSet=\"0\" goal=\"farthest\" filename=\"../examples/stadium/arena.nav\"/>"<<endl; - file<< "-->"<<endl; - file<< "\t\t\t\t<AbsoluteGoal goalSet=\"0\" goal=\"nearest\" perAgent=\"1\" />"<<endl; - file<< "\t\t\t\t<VelComponent type=\"navMesh\" weight=\"1.0\" filename=\"../examples/stadium/arena.nav\" />"<<endl; - file<< "\t\t\t</State>"<<endl; - file<< "\t\t\t<State name=\"Stop1\" speedPolicy=\"min\" final=\"1\">"<<endl; - file<< "\t\t\t\t<HoldPosGoal />"<<endl; - file<< "\t\t\t\t<VelComponent type=\"goal\" weight=\"1.0\"/>"<<endl; - file<< "\t\t\t</State>"<<endl; - file<< ""<<endl; - file<< "\t\t\t<Transition order=\"0\" type=\"goal_circle\" from=\"Walk1\" to=\"Stop1\" radius=\"0.25\" inside=\"1\" />"<<endl; - file<< "\t\t</Behavior>"<<endl; - file<< ""<<endl; - file<< "</Population>"<<endl; - - - file.close(); +void NavMesh::WriteBehavior() +{ + string filename="../pedunc/examples/stadium/arenaB.xml"; + ofstream file(filename.c_str()); + file.precision(2); + file<<fixed; + + if(file.is_open()==false) { + cout <<"could not open the file: "<<filename<<endl; + return; + } + + file<< "<?xml version=\"1.0\"?>"<<endl; + file<< "\t<Population>"<<endl; + + + int goalsetid=0; + //Write the goal set outside + { + file<< "\t\t<GoalSet id=\""<<goalsetid++<<"\" description=\"outside\">"<<endl; + + vector<Point> goals=_building->GetRoom("outside")->GetSubRoom(0)->GetPolygon(); + for(unsigned int g=0; g<goals.size(); g++) { + double factor=(10.0/(goals[g].Norm())-1); + file<< "\t\t\t<Goal type=\"point\" id=\""<<g<<"\" x=\""<< factor*goals[g]._x<<"\" y=\""<<factor*goals[g]._y<<"\"/>"<<endl; + } + file<< "\t\t</GoalSet>"<<endl; + } + + + //write the goal set tunnel + { + file<< "\t\t<GoalSet id=\""<<goalsetid++<<"\" description=\"tunnel\">"<<endl; + + for (map<int, Transition*>::const_iterator itr = _building->GetAllTransitions().begin(); + itr != _building->GetAllTransitions().end(); ++itr) { + + int door=itr->first; + //int door = itr->second->GetUniqueID(); + Transition* cross = itr->second; + const Point& centre = cross->GetCentre(); + + if((cross->Length()<2.6) && (cross->Length()>2.4)) + + file<< "\t\t\t<Goal type=\"point\" id=\""<<door<<"\" x=\""<< centre._x<<"\" y=\""<<centre._y<<"\"/>"<<endl; + } + file<< "\t\t</GoalSet>"<<endl; + } + + //write the goal set promenade + + file<< "\t\t<Behavior class=\"1\">"<<endl; + file<< "\t\t\t<Property name=\"prefSpeed\" type=\"float\" dist=\"c\" value=\"1.3\" />"<<endl; + file<< "\t\t\t<Property type=\"2D\" name=\"stride\" dist=\"c\" factor_value=\"100.57\" buffer_value=\"0.0\" />"<<endl; + file<< ""<<endl; + file<< "\t\t\t<State name=\"Walk1\" speedPolicy=\"min\" final=\"0\" >"<<endl; + file<< "<!--"<<endl; + file<< "<NavMeshGoal goalSet=\"0\" goal=\"farthest\" filename=\"../examples/stadium/arena.nav\"/>"<<endl; + file<< "-->"<<endl; + file<< "\t\t\t\t<AbsoluteGoal goalSet=\"0\" goal=\"nearest\" perAgent=\"1\" />"<<endl; + file<< "\t\t\t\t<VelComponent type=\"navMesh\" weight=\"1.0\" filename=\"../examples/stadium/arena.nav\" />"<<endl; + file<< "\t\t\t</State>"<<endl; + file<< "\t\t\t<State name=\"Stop1\" speedPolicy=\"min\" final=\"1\">"<<endl; + file<< "\t\t\t\t<HoldPosGoal />"<<endl; + file<< "\t\t\t\t<VelComponent type=\"goal\" weight=\"1.0\"/>"<<endl; + file<< "\t\t\t</State>"<<endl; + file<< ""<<endl; + file<< "\t\t\t<Transition order=\"0\" type=\"goal_circle\" from=\"Walk1\" to=\"Stop1\" radius=\"0.25\" inside=\"1\" />"<<endl; + file<< "\t\t</Behavior>"<<endl; + file<< ""<<endl; + file<< "</Population>"<<endl; + + + file.close(); } -void NavMesh::WriteViewer() { - /* - <?xml version="1.0"?> +void NavMesh::WriteViewer() +{ + /* + <?xml version="1.0"?> - <View width="640" height="480"> - <!-- Multiple cameras are mapped to a key from 1-9 in the order they are defined here --> - <Camera xpos="6.53453" ypos="7.05969" zpos="-4.31638" xtgt="0.609475" ytgt="0.961173" ztgt="1.77459" far="200" near="0.01" fov="45" /> - <Camera xpos="-0.947526" ypos="17.2771" zpos="1.64757" xtgt="-0.947526" ytgt="2.61554" ztgt="1.64584" far="200" near="0.01" fov="0.0" /> + <View width="640" height="480"> + <!-- Multiple cameras are mapped to a key from 1-9 in the order they are defined here --> + <Camera xpos="6.53453" ypos="7.05969" zpos="-4.31638" xtgt="0.609475" ytgt="0.961173" ztgt="1.77459" far="200" near="0.01" fov="45" /> + <Camera xpos="-0.947526" ypos="17.2771" zpos="1.64757" xtgt="-0.947526" ytgt="2.61554" ztgt="1.64584" far="200" near="0.01" fov="0.0" /> - <!-- Comment out lights for a constant-illuminated visualization --> - <Light x="1" y="0" z="-1" type="directional" diffR="1.0" diffG="0.8" diffB="0.8" space="camera"/> - <Light x="-1" y="0" z="-1" type="directional" diffR="0.8" diffG="0.8" diffB="1.0" space="camera"/> - <Light x="0" y="1" z="0" type="directional" diffR="0.8" diffG="0.8" diffB="0.8" space="world"/> - </View> - */ + <!-- Comment out lights for a constant-illuminated visualization --> + <Light x="1" y="0" z="-1" type="directional" diffR="1.0" diffG="0.8" diffB="0.8" space="camera"/> + <Light x="-1" y="0" z="-1" type="directional" diffR="0.8" diffG="0.8" diffB="1.0" space="camera"/> + <Light x="0" y="1" z="0" type="directional" diffR="0.8" diffG="0.8" diffB="0.8" space="world"/> + </View> + */ } -void NavMesh::WriteStartPositions() { - - //get the available positions: - - PedDistributor* pDistribution = new PedDistributor(); - - vector< vector<Point > > availablePos = vector< vector<Point> >(); - - for (int r = 0; r < _building->GetNumberOfRooms(); r++) { - vector<Point > freePosRoom = vector<Point > (); - Room* room = _building->GetRoom(r); - if(room->GetCaption()=="outside") continue; - for (int s = 0; s < room->GetNumberOfSubRooms(); s++) { - SubRoom* subr = room->GetSubRoom(s); - vector<Point > pos = pDistribution->PossiblePositions(subr); - freePosRoom.insert(freePosRoom.end(),pos.begin(),pos.end()); - } - availablePos.push_back(freePosRoom); - } - - - string filename="../pedunc/examples/stadium/arenaS.xml"; - ofstream file(filename.c_str()); - file.precision(2); - file<<fixed; - - if(file.is_open()==false){ - cout <<"could not open the file: "<<filename<<endl; - return; - } - - file<< "<?xml version=\"1.0\"?>"<<endl; - file<< "<Experiment version=\"2.0\">"<<endl; - file<< "\t<SpatialQuery>"<<endl; - file<< "\t\t<NavMesh filename=\"../examples/stadium/arena.nav\"/>"<<endl; - file<< "\t</SpatialQuery>"<<endl; - file<< "<!--"<<endl; - file<< "<Elevation>"<<endl; - file<< "<NavMeshElevation filename=\"../examples/stadium/arena.nav\" />"<<endl; - file<< "</Elevation>"<<endl; - file<< "-->"<<endl; - file<< "\t<Boids max_force=\"8\" leak_through=\"0.1\" reaction_time=\"0.5\" />"<<endl; - file<< "\t<Common time_step=\"0.1\" />"<<endl; - file<< "\t<GCF reaction_time=\"0.5\" max_agent_dist=\"2\" max_agent_force=\"3\" agent_interp_width=\"0.1\" nu_agent=\"0.35\" />"<<endl; - file<< "\t<Helbing agent_scale=\"2000\" obstacle_scale=\"4000\" reaction_time=\"0.5\" body_force=\"1200\" friction=\"2400\" force_distance=\"0.015\" />"<<endl; - file<< "\t<Johansson agent_scale=\"25\" obstacle_scale=\"35\" reaction_time=\"0.5\" force_distance=\"0.15\" stride_time=\"0.5\" />"<<endl; - file<< "\t<Karamouzas orient_weight=\"0.8\" fov=\"200\" reaction_time=\"0.4\" wall_steepness=\"2\" wall_distance=\"2\" colliding_count=\"5\" d_min=\"1\" d_mid=\"8\" d_max=\"10\" agent_force=\"4\" />"<<endl; - file<< "\t<Zanlungo agent_scale=\"2000\" obstacle_scale=\"4000\" reaction_time=\"0.5\" force_distance=\"0.005\" />"<<endl; - file<< ""<<endl; - file<< "\t<AgentSet>"<<endl; - file<< "\t\t<Boids tau=\"3\" tauObst=\"6\" />"<<endl; - file<< "\t\t<Common max_neighbors=\"10\" obstacleSet=\"1\" neighbor_dist=\"5\" r=\"0.19\" class=\"1\" pref_speed=\"1.04\" max_speed=\"2\" max_accel=\"5\" />"<<endl; - file<< "\t\t<GCF stand_depth=\"0.18\" move_scale=\"0.53\" slow_width=\"0.25\" sway_change=\"0.05\" orient_weight=\"0.75\" />"<<endl; - file<< "\t\t<Helbing mass=\"80\" />"<<endl; - file<< "\t\t<Johansson fov_weight=\"0.16\" />"<<endl; - file<< "\t\t<Karamouzas personal_space=\"0.69\" anticipation=\"8\" />"<<endl; - file<< "\t\t<RVO tau=\"3\" tauObst=\"0.75\" turningBias=\"1.0\" />"<<endl; - file<< "\t\t<Zanlungo mass=\"80\" orient_weight=\"0.75\" />"<<endl; - file<< ""<<endl; - - - for(int i=0;i<_building->GetNumberOfRooms();i++){ - //int room_id=pBuilding->GetRoom("100")->GetRoomID(); - - Room* room = _building->GetRoom(i); - if(room->GetCaption()=="outside") continue; - if(room->GetCaption()=="150") continue; - int room_id=room->GetID(); - vector<Point > freePosRoom = availablePos[room_id]; - - int nAgentsPerRoom=10; // the number of agents to distribute - for (int a=0;a<nAgentsPerRoom;a++){ - int index = rand() % freePosRoom.size(); - file<< "\t\t<Agent p_x=\""<<freePosRoom[index]._x<<" \"p_y=\""<<freePosRoom[index]._y<<"\"/>"<<endl; - //cout<<"Position: "<<freePosRoom[index].toString()<<endl; - freePosRoom.erase(freePosRoom.begin() + index); - } - - // break; - } - - file<< "\t</AgentSet>"<<endl; - file<< "</Experiment>"<<endl; +void NavMesh::WriteStartPositions() +{ + + //get the available positions: + + PedDistributor* pDistribution = new PedDistributor(); + + vector< vector<Point > > availablePos = vector< vector<Point> >(); + + for (int r = 0; r < _building->GetNumberOfRooms(); r++) { + vector<Point > freePosRoom = vector<Point > (); + Room* room = _building->GetRoom(r); + if(room->GetCaption()=="outside") continue; + for (int s = 0; s < room->GetNumberOfSubRooms(); s++) { + SubRoom* subr = room->GetSubRoom(s); + vector<Point > pos = pDistribution->PossiblePositions(subr); + freePosRoom.insert(freePosRoom.end(),pos.begin(),pos.end()); + } + availablePos.push_back(freePosRoom); + } + + + string filename="../pedunc/examples/stadium/arenaS.xml"; + ofstream file(filename.c_str()); + file.precision(2); + file<<fixed; + + if(file.is_open()==false) { + cout <<"could not open the file: "<<filename<<endl; + return; + } + + file<< "<?xml version=\"1.0\"?>"<<endl; + file<< "<Experiment version=\"2.0\">"<<endl; + file<< "\t<SpatialQuery>"<<endl; + file<< "\t\t<NavMesh filename=\"../examples/stadium/arena.nav\"/>"<<endl; + file<< "\t</SpatialQuery>"<<endl; + file<< "<!--"<<endl; + file<< "<Elevation>"<<endl; + file<< "<NavMeshElevation filename=\"../examples/stadium/arena.nav\" />"<<endl; + file<< "</Elevation>"<<endl; + file<< "-->"<<endl; + file<< "\t<Boids max_force=\"8\" leak_through=\"0.1\" reaction_time=\"0.5\" />"<<endl; + file<< "\t<Common time_step=\"0.1\" />"<<endl; + file<< "\t<GCF reaction_time=\"0.5\" max_agent_dist=\"2\" max_agent_force=\"3\" agent_interp_width=\"0.1\" nu_agent=\"0.35\" />"<<endl; + file<< "\t<Helbing agent_scale=\"2000\" obstacle_scale=\"4000\" reaction_time=\"0.5\" body_force=\"1200\" friction=\"2400\" force_distance=\"0.015\" />"<<endl; + file<< "\t<Johansson agent_scale=\"25\" obstacle_scale=\"35\" reaction_time=\"0.5\" force_distance=\"0.15\" stride_time=\"0.5\" />"<<endl; + file<< "\t<Karamouzas orient_weight=\"0.8\" fov=\"200\" reaction_time=\"0.4\" wall_steepness=\"2\" wall_distance=\"2\" colliding_count=\"5\" d_min=\"1\" d_mid=\"8\" d_max=\"10\" agent_force=\"4\" />"<<endl; + file<< "\t<Zanlungo agent_scale=\"2000\" obstacle_scale=\"4000\" reaction_time=\"0.5\" force_distance=\"0.005\" />"<<endl; + file<< ""<<endl; + file<< "\t<AgentSet>"<<endl; + file<< "\t\t<Boids tau=\"3\" tauObst=\"6\" />"<<endl; + file<< "\t\t<Common max_neighbors=\"10\" obstacleSet=\"1\" neighbor_dist=\"5\" r=\"0.19\" class=\"1\" pref_speed=\"1.04\" max_speed=\"2\" max_accel=\"5\" />"<<endl; + file<< "\t\t<GCF stand_depth=\"0.18\" move_scale=\"0.53\" slow_width=\"0.25\" sway_change=\"0.05\" orient_weight=\"0.75\" />"<<endl; + file<< "\t\t<Helbing mass=\"80\" />"<<endl; + file<< "\t\t<Johansson fov_weight=\"0.16\" />"<<endl; + file<< "\t\t<Karamouzas personal_space=\"0.69\" anticipation=\"8\" />"<<endl; + file<< "\t\t<RVO tau=\"3\" tauObst=\"0.75\" turningBias=\"1.0\" />"<<endl; + file<< "\t\t<Zanlungo mass=\"80\" orient_weight=\"0.75\" />"<<endl; + file<< ""<<endl; + + + for(int i=0; i<_building->GetNumberOfRooms(); i++) { + //int room_id=pBuilding->GetRoom("100")->GetRoomID(); + + Room* room = _building->GetRoom(i); + if(room->GetCaption()=="outside") continue; + if(room->GetCaption()=="150") continue; + int room_id=room->GetID(); + vector<Point > freePosRoom = availablePos[room_id]; + + int nAgentsPerRoom=10; // the number of agents to distribute + for (int a=0; a<nAgentsPerRoom; a++) { + int index = rand() % freePosRoom.size(); + file<< "\t\t<Agent p_x=\""<<freePosRoom[index]._x<<" \"p_y=\""<<freePosRoom[index]._y<<"\"/>"<<endl; + //cout<<"Position: "<<freePosRoom[index].toString()<<endl; + freePosRoom.erase(freePosRoom.begin() + index); + } + + // break; + } + + file<< "\t</AgentSet>"<<endl; + file<< "</Experiment>"<<endl; } -void NavMesh::UpdateEdges() { - - for(unsigned int n=0;n<_nodes.size();n++){ - JNode* node= _nodes[n]; - - std::sort( node->pPortals.begin(), node->pPortals.end() ); - node->pPortals.erase( std::unique( node->pPortals.begin(), node->pPortals.end() ), node->pPortals.end() ); - - for(unsigned int i=0;i<node->pPortals.size();i++){ - JEdge* e= _edges[node->pPortals[i]]; - if(e->pNode0<0 && e->pNode1!=node->id) { - e->pNode0=node->id; - }else - if(e->pNode1<0 && e->pNode0!=node->id){ - e->pNode1=node->id; - } - - if(e->pNode0>e->pNode1){ - swap(e->pNode0,e->pNode1); - } - if((e->pNode0==e->pNode1) && (e->pNode1!=-1)){ - cout<<"Duplicate: "<<endl; - cout<<"edge id: "<< e->id <<endl; - cout<<"node 0 : "<< e->pNode0 <<endl; - cout<<"node 1 : "<< e->pNode1 <<endl; - exit(0); - } - } - } +void NavMesh::UpdateEdges() +{ + + for(unsigned int n=0; n<_nodes.size(); n++) { + JNode* node= _nodes[n]; + + std::sort( node->pPortals.begin(), node->pPortals.end() ); + node->pPortals.erase( std::unique( node->pPortals.begin(), node->pPortals.end() ), node->pPortals.end() ); + + for(unsigned int i=0; i<node->pPortals.size(); i++) { + JEdge* e= _edges[node->pPortals[i]]; + if(e->pNode0<0 && e->pNode1!=node->id) { + e->pNode0=node->id; + } else if(e->pNode1<0 && e->pNode0!=node->id) { + e->pNode1=node->id; + } + + if(e->pNode0>e->pNode1) { + swap(e->pNode0,e->pNode1); + } + if((e->pNode0==e->pNode1) && (e->pNode1!=-1)) { + cout<<"Duplicate: "<<endl; + cout<<"edge id: "<< e->id <<endl; + cout<<"node 0 : "<< e->pNode0 <<endl; + cout<<"node 1 : "<< e->pNode1 <<endl; + exit(0); + } + } + } } -void NavMesh::UpdateObstacles() { +void NavMesh::UpdateObstacles() +{ - for(unsigned int n=0;n<_nodes.size();n++){ - JNode* node= _nodes[n]; - for(unsigned int i=0;i<node->pObstacles.size();i++){ - JObstacle* o= _obst[node->pObstacles[i]]; + for(unsigned int n=0; n<_nodes.size(); n++) { + JNode* node= _nodes[n]; + for(unsigned int i=0; i<node->pObstacles.size(); i++) { + JObstacle* o= _obst[node->pObstacles[i]]; - if(o->pNode0<0) { - o->pNode0=node->id; - } - } - } + if(o->pNode0<0) { + o->pNode0=node->id; + } + } + } } //void NavMesh::ComputePlaneEquation(SubRoom* sub, double* coefficents) { @@ -2405,450 +2421,458 @@ void NavMesh::UpdateObstacles() { // //} -void NavMesh::ComputePlanesEquation() { - - //first compute the stairs equations. - // all other equations are derived from there. - - ComputeStairsEquation(); - - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* r = _building->GetRoom(i); - //if(r->GetCaption()!="090") continue; - - for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { - SubRoom* sub = r->GetSubRoom(k); - - Stair* stair=dynamic_cast<Stair*>(sub); - - if(stair==NULL) - { - bool connection=false; - - //check if the subroom is connected with a stair - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* r = _building->GetRoom(i); - for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { - SubRoom* s = r->GetSubRoom(k); - Stair* st=dynamic_cast<Stair*>(s); - //if ((st!=NULL) && (s->GetSubRoomID()!=sub->GetSubRoomID()) ){ - if (st!=NULL){ - //if(st->GetAllCrossings().size()==2) continue; - if(sub->IsDirectlyConnectedWith(st)){ - //get the middle point of the crossing - //check the crossings - const vector<Crossing*>& crossings1 = sub->GetAllCrossings(); - const vector<Crossing*>& crossings2 = st->GetAllCrossings(); - for (unsigned int c1 = 0; c1 < crossings1.size(); c1++) { - for (unsigned int c2 = 0; c2 < crossings2.size(); c2++) { - int uid1 = crossings1[c1]->GetUniqueID(); - int uid2 = crossings2[c2]->GetUniqueID(); - // ignore my transition - if (uid1 == uid2){ - Point center=crossings1[c1]->GetCentre(); - double elevation = st->GetElevation(center); - sub->SetPlanEquation(0.0,0.0,elevation); - connection=true; - goto DONE; // just out of this ugly loop - } - } - } - const vector<Transition*>& transitions1 = sub->GetAllTransitions(); - const vector<Transition*>& transitions2 = st->GetAllTransitions(); - for (unsigned int t1 = 0; t1 < transitions1.size(); t1++) { - for (unsigned int t2 = 0; t2 < transitions2.size(); t2++) { - int uid1 = transitions1[t1]->GetUniqueID(); - int uid2 = transitions2[t2]->GetUniqueID(); - // ignore my transition - if (uid1 == uid2){ - Point center=transitions1[t1]->GetCentre(); - double elevation = st->GetElevation(center); - sub->SetPlanEquation(0.0,0.0,elevation); - connection=true; - goto DONE; // just out of this ugly loop - } - } - } - } - } +void NavMesh::ComputePlanesEquation() +{ + + //first compute the stairs equations. + // all other equations are derived from there. + + ComputeStairsEquation(); + + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* r = _building->GetRoom(i); + //if(r->GetCaption()!="090") continue; + + for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { + SubRoom* sub = r->GetSubRoom(k); + + Stair* stair=dynamic_cast<Stair*>(sub); + + if(stair==NULL) { + bool connection=false; + + //check if the subroom is connected with a stair + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* r = _building->GetRoom(i); + for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { + SubRoom* s = r->GetSubRoom(k); + Stair* st=dynamic_cast<Stair*>(s); + //if ((st!=NULL) && (s->GetSubRoomID()!=sub->GetSubRoomID()) ){ + if (st!=NULL) { + //if(st->GetAllCrossings().size()==2) continue; + if(sub->IsDirectlyConnectedWith(st)) { + //get the middle point of the crossing + //check the crossings + const vector<Crossing*>& crossings1 = sub->GetAllCrossings(); + const vector<Crossing*>& crossings2 = st->GetAllCrossings(); + for (unsigned int c1 = 0; c1 < crossings1.size(); c1++) { + for (unsigned int c2 = 0; c2 < crossings2.size(); c2++) { + int uid1 = crossings1[c1]->GetUniqueID(); + int uid2 = crossings2[c2]->GetUniqueID(); + // ignore my transition + if (uid1 == uid2) { + Point center=crossings1[c1]->GetCentre(); + double elevation = st->GetElevation(center); + sub->SetPlanEquation(0.0,0.0,elevation); + connection=true; + goto DONE; // just out of this ugly loop + } + } + } + const vector<Transition*>& transitions1 = sub->GetAllTransitions(); + const vector<Transition*>& transitions2 = st->GetAllTransitions(); + for (unsigned int t1 = 0; t1 < transitions1.size(); t1++) { + for (unsigned int t2 = 0; t2 < transitions2.size(); t2++) { + int uid1 = transitions1[t1]->GetUniqueID(); + int uid2 = transitions2[t2]->GetUniqueID(); + // ignore my transition + if (uid1 == uid2) { + Point center=transitions1[t1]->GetCentre(); + double elevation = st->GetElevation(center); + sub->SetPlanEquation(0.0,0.0,elevation); + connection=true; + goto DONE; // just out of this ugly loop + } + } } - } - // do the projection - DONE: - if(connection==false){ - sub->SetPlanEquation(0.0,0.0,r->GetZPos()); - //cout<<"base: "<< sub->GetAllCrossings().size()<<endl; - } - } - } - } + } + } + } + } + // do the projection +DONE: + if(connection==false) { + sub->SetPlanEquation(0.0,0.0,r->GetZPos()); + //cout<<"base: "<< sub->GetAllCrossings().size()<<endl; + } + } + } + } } -void NavMesh::UpdateNodes() { - //loop over the nodes - //loop over the obstacles and connect the obstacles which - //share an Obstacle. - - for (unsigned int i = 0; i < _nodes.size(); i++) { - JNode* node = _nodes[i]; - //node->pObstacles.clear(); - - for (unsigned int j = 0; j < node->pHull.size(); j++) { - const Point& V = _vertices[node->pHull[j].id]->pPos; - for (unsigned int k = 0; k < _obst.size(); k++) { - const Point& A = _obst[k]->pEnd.pPos; - const Point& B = _obst[k]->pStart.pPos; - if ( (A==V) || (B==V) ) node->pObstacles.push_back(_obst[k]->id); - } - } - std::sort( node->pObstacles.begin(), node->pObstacles.end() ); - node->pObstacles.erase( std::unique( node->pObstacles.begin(), node->pObstacles.end() ), node->pObstacles.end() ); - } +void NavMesh::UpdateNodes() +{ + //loop over the nodes + //loop over the obstacles and connect the obstacles which + //share an Obstacle. + + for (unsigned int i = 0; i < _nodes.size(); i++) { + JNode* node = _nodes[i]; + //node->pObstacles.clear(); + + for (unsigned int j = 0; j < node->pHull.size(); j++) { + const Point& V = _vertices[node->pHull[j].id]->pPos; + for (unsigned int k = 0; k < _obst.size(); k++) { + const Point& A = _obst[k]->pEnd.pPos; + const Point& B = _obst[k]->pStart.pPos; + if ( (A==V) || (B==V) ) node->pObstacles.push_back(_obst[k]->id); + } + } + std::sort( node->pObstacles.begin(), node->pObstacles.end() ); + node->pObstacles.erase( std::unique( node->pObstacles.begin(), node->pObstacles.end() ), node->pObstacles.end() ); + } } -void NavMesh::ComputeStairsEquation() { - - double StairAngle=34.0; // degrees - double theta = ( StairAngle * M_PI / 180.0 ); - - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* r = _building->GetRoom(i); - //cout<<"room: "<<r->GetCaption()<<endl; - //cout<<"elevation: "<<base<<endl; - - //if(r->GetCaption()!="090") continue; - - for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { - SubRoom* sub = r->GetSubRoom(k); - - Stair* stair=dynamic_cast<Stair*>(sub); - double base=r->GetZPos(); - - - if(stair!=NULL) - { // we are having a stair - //return; - // cout<<"area: " <<stair->GetArea()<<endl; - // if(stair->GetArea()<StairAreaToIgnore) { - // return; - // } - - if(stair->GetAllCrossings().size()<=4) { - stair->SetPlanEquation(0.0,0.0,r->GetZPos()); - //cout<<"elevation: " <<base<<endl; - //getc(stdin); - continue; - } - - // looking for the normal vector - Point A; - Point B; - Point C; - Point D; - bool finished=false; - vector<Point> poly=sub->GetPolygon(); - { - Point vecAB= poly[1]-poly[0]; - Point vecBC= poly[2]-poly[1]; - - double det=vecAB.Det(vecBC); - if(fabs(det)>J_EPS) { - std::reverse(poly.begin(), poly.end()); - //cout<<"stair is ccw:"<<endl; - } - } - - //loop until we get something - while ( ! finished) { - - for (unsigned int i1=0;i1<4;i1++){ - - int i2 = (i1 + 1) % poly.size(); - int i3 = (i2 + 1) % poly.size(); - int i4 = (i3 + 1) % poly.size(); - Point p1 = poly[i1]; - Point p2 = poly[i2]; - Point p3 = poly[i3]; - Point p4 = poly[i4]; - if( (p1-p2).Norm() < (p3-p2).Norm() ){ - //take the closest to the center of the stadium - double dist1= Line(p1,p2).DistTo(Point(0.0,0.0)); - double dist2= Line(p3,p4).DistTo(Point(0.0,0.0)); - if(dist1<dist2){ - Point D0 = p2 - p1; - Point D1 = Point(0.0,0.0)-p1; - //Point D1 = p1 - Point(0,0); - if (D0.Det(D1) > 0) { - D=p1; - A=p2; - B=p3; - C=p4; - //finished=true; - }else { - A=p1; - B=p4; - C=p3; - D=p2; - } - finished=true; - } - // if(dist1<dist2){ - // Point D0 = p1 - p2; - // //Point D1 = Point(0,0)-p1; - // Point D1 = p1 - Point(0,0); - // if (D0.Det(D1) > 0) { - // D=p1; - // A=p2; - // B=p3; - // C=p4; - // //finished=true; - // }else { - // A=p1; - // B=p4; - // C=p3; - // D=p2; - // } - // finished=true; - // } - } +void NavMesh::ComputeStairsEquation() +{ + + double StairAngle=34.0; // degrees + double theta = ( StairAngle * M_PI / 180.0 ); + + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* r = _building->GetRoom(i); + //cout<<"room: "<<r->GetCaption()<<endl; + //cout<<"elevation: "<<base<<endl; + + //if(r->GetCaption()!="090") continue; + + for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { + SubRoom* sub = r->GetSubRoom(k); + + Stair* stair=dynamic_cast<Stair*>(sub); + double base=r->GetZPos(); + + + if(stair!=NULL) { + // we are having a stair + //return; + // cout<<"area: " <<stair->GetArea()<<endl; + // if(stair->GetArea()<StairAreaToIgnore) { + // return; + // } + + if(stair->GetAllCrossings().size()<=4) { + stair->SetPlanEquation(0.0,0.0,r->GetZPos()); + //cout<<"elevation: " <<base<<endl; + //getc(stdin); + continue; + } + + // looking for the normal vector + Point A; + Point B; + Point C; + Point D; + bool finished=false; + vector<Point> poly=sub->GetPolygon(); + { + Point vecAB= poly[1]-poly[0]; + Point vecBC= poly[2]-poly[1]; + + double det=vecAB.Det(vecBC); + if(fabs(det)>J_EPS) { + std::reverse(poly.begin(), poly.end()); + //cout<<"stair is ccw:"<<endl; + } + } + + //loop until we get something + while ( ! finished) { + + for (unsigned int i1=0; i1<4; i1++) { + + int i2 = (i1 + 1) % poly.size(); + int i3 = (i2 + 1) % poly.size(); + int i4 = (i3 + 1) % poly.size(); + Point p1 = poly[i1]; + Point p2 = poly[i2]; + Point p3 = poly[i3]; + Point p4 = poly[i4]; + if( (p1-p2).Norm() < (p3-p2).Norm() ) { + //take the closest to the center of the stadium + double dist1= Line(p1,p2).DistTo(Point(0.0,0.0)); + double dist2= Line(p3,p4).DistTo(Point(0.0,0.0)); + if(dist1<dist2) { + Point D0 = p2 - p1; + Point D1 = Point(0.0,0.0)-p1; + //Point D1 = p1 - Point(0,0); + if (D0.Det(D1) > 0) { + D=p1; + A=p2; + B=p3; + C=p4; + //finished=true; + } else { + A=p1; + B=p4; + C=p3; + D=p2; } - } - - - - double vecDA[3]; - vecDA[0]= (A-D)._x; - vecDA[1]= (A-D)._y; - vecDA[2]= 0.0; - - double vecDC[3]; - vecDC[0]= (C-D)._x; - vecDC[1]= (C-D)._y; - vecDC[2]= (C-D).Norm()*tan(theta); - - double vecNormal[3]; - vecNormal[0]= vecDA[1]*vecDC[2] - vecDA[2]*vecDC[1]; - vecNormal[1]= vecDA[2]*vecDC[0] - vecDA[0]*vecDC[2]; - vecNormal[2]= vecDA[0]*vecDC[1] - vecDA[1]*vecDC[0]; - - - if((C-D).Norm() < 7.4 ){ - base= base - (C-D).Norm()*tan(theta) ; - //cout<<" room: "<<r->GetCaption()<<endl; - } - - // the equation of the plan is given as: Ax+By+Cz+d=0; - // using the Point A: - double d = - (vecNormal[0]*A._x+vecNormal[1]*A._y+vecNormal[2]*base); - double coef[3]; - coef[0]= - vecNormal[0] / vecNormal[2]; - coef[1]= - vecNormal[1] / vecNormal[2]; - coef[2]= - d / vecNormal[2]; - sub->SetPlanEquation(coef[0],coef[1],coef[2]); - } - } - } + finished=true; + } + // if(dist1<dist2){ + // Point D0 = p1 - p2; + // //Point D1 = Point(0,0)-p1; + // Point D1 = p1 - Point(0,0); + // if (D0.Det(D1) > 0) { + // D=p1; + // A=p2; + // B=p3; + // C=p4; + // //finished=true; + // }else { + // A=p1; + // B=p4; + // C=p3; + // D=p2; + // } + // finished=true; + // } + } + } + } + + + + double vecDA[3]; + vecDA[0]= (A-D)._x; + vecDA[1]= (A-D)._y; + vecDA[2]= 0.0; + + double vecDC[3]; + vecDC[0]= (C-D)._x; + vecDC[1]= (C-D)._y; + vecDC[2]= (C-D).Norm()*tan(theta); + + double vecNormal[3]; + vecNormal[0]= vecDA[1]*vecDC[2] - vecDA[2]*vecDC[1]; + vecNormal[1]= vecDA[2]*vecDC[0] - vecDA[0]*vecDC[2]; + vecNormal[2]= vecDA[0]*vecDC[1] - vecDA[1]*vecDC[0]; + + + if((C-D).Norm() < 7.4 ) { + base= base - (C-D).Norm()*tan(theta) ; + //cout<<" room: "<<r->GetCaption()<<endl; + } + + // the equation of the plan is given as: Ax+By+Cz+d=0; + // using the Point A: + double d = - (vecNormal[0]*A._x+vecNormal[1]*A._y+vecNormal[2]*base); + double coef[3]; + coef[0]= - vecNormal[0] / vecNormal[2]; + coef[1]= - vecNormal[1] / vecNormal[2]; + coef[2]= - d / vecNormal[2]; + sub->SetPlanEquation(coef[0],coef[1],coef[2]); + } + } + } } -bool NavMesh::IsCircleVisibleFromLine(const Point& center, double radius, const Line& segment){ - - int nLine=0; - - for(double alpha=0.0;alpha<=2*M_PI;alpha+=0.01){ - - bool isVisible=true; - bool done=false; +bool NavMesh::IsCircleVisibleFromLine(const Point& center, double radius, const Line& segment) +{ - double x= radius*cos(alpha); - double y= radius*sin(alpha); - Point point_on_circle = Point(x,y) + center; - //test must be done for the two points separately - Line seg1=Line(segment.GetPoint1(),point_on_circle); - //Line seg2=Line(segment.GetPoint2(),point_on_circle); + int nLine=0; - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* r = _building->GetRoom(i); + for(double alpha=0.0; alpha<=2*M_PI; alpha+=0.01) { - //skip the virtual room containing the complete geometry - if(r->GetCaption()=="outside") continue; - - for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { - SubRoom* s = r->GetSubRoom(k); - const vector<Wall>& walls = s->GetAllWalls(); - //const vector<Transition*>& transitions = s->GetAllTransitions(); - - for (unsigned w = 0; w < walls.size(); w++) { - - //if(walls[w]==segment) continue; - // dont check if they share a common vertex - //if(walls[w].ShareCommonPointWith(segment)) continue; - if(walls[w].HasEndPoint(segment.GetPoint1())) continue; - - if(seg1.IntersectionWith(walls[w])) { - //cout<<"X"; - done=true; - isVisible=false; - break; - } - } - if(!done) - for (map<int, Transition*>::const_iterator itr = _building->GetAllTransitions().begin(); - itr != _building->GetAllTransitions().end(); ++itr) { - Transition* cross = itr->second; - //if(cross->operator ==(segment)) continue; - if(cross->IntersectionWith(segment)){ - done=true; - isVisible=false; - break; - } - } - - if(done) break; - } - if(done) break; - } - - //one visibility line was found - if(isVisible==true) { - nLine++; - break; - } - } - - //the first point failed. - // check the second one - if(nLine==0) return false; - - //if (nLine==1) return true; - - //restart the same procedure with the second point - - for(double alpha=0.0;alpha<=2*M_PI;alpha+=0.01){ - - bool isVisible=true; - bool done=false; - - double x= radius*cos(alpha); - double y= radius*sin(alpha); - Point point_on_circle = Point(x,y) + center; - //test must be done for the two points separately - //Line seg1=Line(segment.GetPoint1(),point_on_circle); - Line seg2=Line(segment.GetPoint2(),point_on_circle); - - - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* r = _building->GetRoom(i); - - //skip the virtual room containing the complete geometry - if(r->GetCaption()=="outside") continue; - - for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { - SubRoom* s = r->GetSubRoom(k); - const vector<Wall>& walls = s->GetAllWalls(); - - for (unsigned w = 0; w < walls.size(); w++) { - - //if(walls[w]==segment) continue; - //if(walls[w].ShareCommonPointWith(segment)) continue; - if(walls[w].HasEndPoint(segment.GetPoint2())) continue; - - if(seg2.IntersectionWith(walls[w])) { - //cout<<"X"; - done=true; - isVisible=false; - break; - } - } - if(!done) - for (map<int, Transition*>::const_iterator itr = _building->GetAllTransitions().begin(); - itr != _building->GetAllTransitions().end(); ++itr) { - Transition* cross = itr->second; - //if(cross->operator ==(segment)) continue; - if(cross->IntersectionWith(segment)){ - done=true; - isVisible=false; - break; - } - } - if(done) break; - } - if(done) break; - } - - //one visibility line was found - if(isVisible==true) { - nLine++; - break; - } - } - - cout<<"nline: " <<nLine<<endl; - if(nLine==2) return true; - else return false; + bool isVisible=true; + bool done=false; + + double x= radius*cos(alpha); + double y= radius*sin(alpha); + Point point_on_circle = Point(x,y) + center; + //test must be done for the two points separately + Line seg1=Line(segment.GetPoint1(),point_on_circle); + //Line seg2=Line(segment.GetPoint2(),point_on_circle); + + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* r = _building->GetRoom(i); + + //skip the virtual room containing the complete geometry + if(r->GetCaption()=="outside") continue; + + for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { + SubRoom* s = r->GetSubRoom(k); + const vector<Wall>& walls = s->GetAllWalls(); + //const vector<Transition*>& transitions = s->GetAllTransitions(); + + for (unsigned w = 0; w < walls.size(); w++) { + + //if(walls[w]==segment) continue; + // dont check if they share a common vertex + //if(walls[w].ShareCommonPointWith(segment)) continue; + if(walls[w].HasEndPoint(segment.GetPoint1())) continue; + + if(seg1.IntersectionWith(walls[w])) { + //cout<<"X"; + done=true; + isVisible=false; + break; + } + } + if(!done) + for (map<int, Transition*>::const_iterator itr = _building->GetAllTransitions().begin(); + itr != _building->GetAllTransitions().end(); ++itr) { + Transition* cross = itr->second; + //if(cross->operator ==(segment)) continue; + if(cross->IntersectionWith(segment)) { + done=true; + isVisible=false; + break; + } + } + + if(done) break; + } + if(done) break; + } + + //one visibility line was found + if(isVisible==true) { + nLine++; + break; + } + } + + //the first point failed. + // check the second one + if(nLine==0) return false; + + //if (nLine==1) return true; + + //restart the same procedure with the second point + + for(double alpha=0.0; alpha<=2*M_PI; alpha+=0.01) { + + bool isVisible=true; + bool done=false; + + double x= radius*cos(alpha); + double y= radius*sin(alpha); + Point point_on_circle = Point(x,y) + center; + //test must be done for the two points separately + //Line seg1=Line(segment.GetPoint1(),point_on_circle); + Line seg2=Line(segment.GetPoint2(),point_on_circle); + + + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* r = _building->GetRoom(i); + + //skip the virtual room containing the complete geometry + if(r->GetCaption()=="outside") continue; + + for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { + SubRoom* s = r->GetSubRoom(k); + const vector<Wall>& walls = s->GetAllWalls(); + + for (unsigned w = 0; w < walls.size(); w++) { + + //if(walls[w]==segment) continue; + //if(walls[w].ShareCommonPointWith(segment)) continue; + if(walls[w].HasEndPoint(segment.GetPoint2())) continue; + + if(seg2.IntersectionWith(walls[w])) { + //cout<<"X"; + done=true; + isVisible=false; + break; + } + } + if(!done) + for (map<int, Transition*>::const_iterator itr = _building->GetAllTransitions().begin(); + itr != _building->GetAllTransitions().end(); ++itr) { + Transition* cross = itr->second; + //if(cross->operator ==(segment)) continue; + if(cross->IntersectionWith(segment)) { + done=true; + isVisible=false; + break; + } + } + if(done) break; + } + if(done) break; + } + + //one visibility line was found + if(isVisible==true) { + nLine++; + break; + } + } + + cout<<"nline: " <<nLine<<endl; + if(nLine==2) return true; + else return false; } -void NavMesh::Test(){ - - Log->Write("INFO:\tValidating the generated mesh"); - - for ( int e=0;e< (int)_edges.size();e++){ - if(e!=_edges[e]->id){ - cout<<"Test failed by edge: "<<e<<" != "<<_edges[e]->id<<endl; - exit(EXIT_FAILURE); - } - if(_edges[e]->pNode0==-1){ - cout<<"edge id: " <<_edges[e]->id<<endl; - cout<<"Node 0 id: "<< _edges[e]->pNode0<<endl; - cout<<"Node 1 id: "<< _edges[e]->pNode1<<endl; - cout<<"test failed"<<endl; - exit(EXIT_FAILURE); - } - if( (_edges[e]->pNode1)==-1){ - cout<<"edge id: " <<_edges[e]->id<<endl; - cout<<"Node 0 id: "<< _edges[e]->pNode0<<endl; - cout<<"Node 1 id: "<< _edges[e]->pNode1<<endl; - cout<<"test failed"<<endl; - } - if( _edges[e]->pNode1==_edges[e]->pNode0){ - cout<<"edge id: " <<_edges[e]->id<<endl; - cout<<"Node 0 id: "<< _edges[e]->pNode0<<endl; - cout<<"Node 1 id: "<< _edges[e]->pNode1<<endl; - cout<<"test failed"<<endl; - exit(EXIT_FAILURE); - } - } - - for ( int i=0;i<(int)_obst.size();i++){ - if(i!=_obst[i]->id){ - cout<<"Test failed by Obstacle: "<<i<<" != "<<_obst[i]->id<<endl; - exit(EXIT_FAILURE); - } - if((_obst[i]->pNode0)==-1){ - cout<<"Node 0 id (obst): "<< _obst[i]->pNode0<<" for obstacle"<<endl; - cout<<"test failed"<<endl; - exit(EXIT_FAILURE); - } - - } - Log->Write("INFO:\t...Done!"); +void NavMesh::Test() +{ + + Log->Write("INFO:\tValidating the generated mesh"); + + for ( int e=0; e< (int)_edges.size(); e++) { + if(e!=_edges[e]->id) { + cout<<"Test failed by edge: "<<e<<" != "<<_edges[e]->id<<endl; + exit(EXIT_FAILURE); + } + if(_edges[e]->pNode0==-1) { + cout<<"edge id: " <<_edges[e]->id<<endl; + cout<<"Node 0 id: "<< _edges[e]->pNode0<<endl; + cout<<"Node 1 id: "<< _edges[e]->pNode1<<endl; + cout<<"test failed"<<endl; + exit(EXIT_FAILURE); + } + if( (_edges[e]->pNode1)==-1) { + cout<<"edge id: " <<_edges[e]->id<<endl; + cout<<"Node 0 id: "<< _edges[e]->pNode0<<endl; + cout<<"Node 1 id: "<< _edges[e]->pNode1<<endl; + cout<<"test failed"<<endl; + } + if( _edges[e]->pNode1==_edges[e]->pNode0) { + cout<<"edge id: " <<_edges[e]->id<<endl; + cout<<"Node 0 id: "<< _edges[e]->pNode0<<endl; + cout<<"Node 1 id: "<< _edges[e]->pNode1<<endl; + cout<<"test failed"<<endl; + exit(EXIT_FAILURE); + } + } + + for ( int i=0; i<(int)_obst.size(); i++) { + if(i!=_obst[i]->id) { + cout<<"Test failed by Obstacle: "<<i<<" != "<<_obst[i]->id<<endl; + exit(EXIT_FAILURE); + } + if((_obst[i]->pNode0)==-1) { + cout<<"Node 0 id (obst): "<< _obst[i]->pNode0<<" for obstacle"<<endl; + cout<<"test failed"<<endl; + exit(EXIT_FAILURE); + } + + } + Log->Write("INFO:\t...Done!"); } -const std::vector<NavMesh::JEdge*>& NavMesh::GetEdges() const { - return _edges; +const std::vector<NavMesh::JEdge*>& NavMesh::GetEdges() const +{ + return _edges; } -const std::vector<NavMesh::JNode*>& NavMesh::GetNodes() const { - return _nodes; +const std::vector<NavMesh::JNode*>& NavMesh::GetNodes() const +{ + return _nodes; } -const std::vector<NavMesh::JObstacle*>& NavMesh::GetObst() const { - return _obst; +const std::vector<NavMesh::JObstacle*>& NavMesh::GetObst() const +{ + return _obst; } -const std::vector<NavMesh::JVertex*>& NavMesh::GetVertices() const { - return _vertices; +const std::vector<NavMesh::JVertex*>& NavMesh::GetVertices() const +{ + return _vertices; } diff --git a/routing/NavMesh.h b/routing/NavMesh.h index e22f00333539df6b760dccd7bcf98ac31c587ff3..d71598382da2e6773078cae7350112cc7ebde01e 100644 --- a/routing/NavMesh.h +++ b/routing/NavMesh.h @@ -27,239 +27,234 @@ class NavMesh { - class JVertex { - public: - Point pPos; - int id; - bool operator==(const JVertex& v) const { - return v.pPos==pPos; - } - bool operator< (const JVertex& v) const{ - return v.pPos._x<pPos._x; - } - bool operator> (const JVertex& v) const{ - return v.pPos._x>pPos._x; - } - - }; - - class JNode { - public: - std::string pGroup; - Point pCentroid; - int id; - std::vector<JVertex> pHull; - std::vector<int> pObstacles; - std::vector<int> pPortals; - double pNormalVec[3]; - - bool operator()(JNode*a ,JNode* b){ - return a->pGroup < b->pGroup; - } - - bool operator==(const JNode& other){ - - if(pCentroid!=other.pCentroid) return false; - if(pObstacles.size()!=other.pObstacles.size()) return false; - if(pPortals.size()!=other.pPortals.size()) return false; - - - // the obstacles and the portals are sorted - for(unsigned int s=0;s<pPortals.size();s++){ - if(pPortals[s]!=other.pPortals[s]) return false; - } - for(unsigned int s=0;s<pObstacles.size();s++){ - if(pObstacles[s]!=other.pObstacles[s]) return false; - } - return true; - } - - ///http://stackoverflow.com/questions/471962/how-do-determine-if-a-polygon-is-complex-convex-nonconvex - bool IsConvex(){ - - unsigned int hsize=pHull.size(); - unsigned int pos=0; - unsigned int neg=0; - - for(unsigned int i=0;i<hsize;i++) - { - Point vecAB= pHull[(i+1)%hsize].pPos-pHull[i%hsize].pPos; - Point vecBC= pHull[(i+2)%hsize].pPos-pHull[(i+1)%hsize].pPos; - double det= vecAB.Det(vecBC); - if(fabs(det)<J_EPS) det=0.0; - - if(det<0.0){ - neg++; + class JVertex { + public: + Point pPos; + int id; + bool operator==(const JVertex& v) const { + return v.pPos==pPos; } - else if(det>0.0) - { - pos++; - } - else - { - pos++; - neg++; - } - - } - - if ( (pos==hsize ) || (neg==hsize) ) { - return true; - } - return false; - } - - ///http://stackoverflow.com/questions/9473570/polygon-vertices-clockwise-or-counterclockwise/ - bool IsClockwise(){ - if(pHull.size()<3){ - std::cerr<<"You need at least 3 vertices. JNode ID ["<<id<<" ]"<<std::endl; - exit(EXIT_FAILURE); - } - - Point vecAB= pHull[1].pPos-pHull[0].pPos; - Point vecBC= pHull[2].pPos-pHull[1].pPos; - - double det=vecAB.Det(vecBC); - if(fabs(det)<J_EPS) det=0.0; - - return ( det<=0.0 ); - } - - - }; - - class JEdge { - public: - int id; - JVertex pStart; - JVertex pEnd; - //Point pDisp; - int pNode0; - int pNode1; - JEdge(){ - id=-1; - pNode0=-1; - pNode1=-1; - } - }; - - class JObstacle { - public: - int id; - JVertex pStart; - JVertex pEnd; - //Point pDisp; - int pNode0; - int pNextObst; - - int GetCommonVertex(JObstacle* obst){ - if(obst->pEnd.id==pEnd.id) return pEnd.id; - if(obst->pEnd.id==pStart.id) return pStart.id; - if(obst->pStart.id==pStart.id) return pStart.id; - if(obst->pStart.id==pEnd.id) return pEnd.id; - return -1; - } - }; - - - - template<typename A> - bool IsElementInVector(const std::vector<A> &vec, A& el) { - typename std::vector<A>::const_iterator it; - it = std::find (vec.begin(), vec.end(), el); - if(it==vec.end()){ - return false; - }else{ - return true; - } - } - - - private: - std::vector<JVertex*> _vertices; - std::vector<JEdge*> _edges; - std::vector<JObstacle*> _obst; - std::vector<JNode*> _nodes; - Building* _building; - - std::vector<JNode*> new_nodes; - std::vector<int> problem_nodes; - - //this is used for subroom with obstacles - std::map<int, std::pair<int,int> > map_node_to_subroom; - - // Check the created navmesh for convex polygons - // convexify the created nav mesh - void Convexify(); - - // Add the additional surrounding world JObstacle - // and triangulate - void Finalize(); - - void FinalizeAlphaShape(); - - /** - * @return true if there is a visibility line between the segment and a portion of the circle - */ - bool IsCircleVisibleFromLine(const Point& center, double radius, const Line& segment); - - void ComputePlaneEquation(SubRoom* sub, double* coefficents); - - void ComputeStairsEquation(); - void ComputePlanesEquation(); - - // Triangulate a subroom possibly with obstacles - void Triangulate(SubRoom* sub); - void Triangulate(JNode* JNode); - - /// Return the id of the JEdge - int IsPortal(Point& p1, Point& p2); - /// Return the id of the JObstacle - int IsObstacle(Point& p1, Point& p2); - - - public: - - NavMesh(Building* b); - virtual ~NavMesh(); - void BuildNavMesh(); - void WriteToFile(std::string fileName); - void WriteToString(std::string& output); - void WriteToFileTraVisTo(std::string fileName); - void WriteToFileTraVisTo(std::string fileName, const std::vector<Point>& points); - void WriteToFileTraVisTo(std::string fileName, JNode* node); - - int AddVertex(JVertex* v); - int AddEdge(JEdge* e); - int AddObst(JObstacle* o); - int AddNode(JNode* n); - - ///return the JVertex with the corresponding point - JVertex* GetVertex(const Point& p); - void DumpNode(int id); - void DumpEdge(int id); - void DumpObstacle(int id); - - /// Write the simulation scenario for the - /// pedunc simulator - void WriteScenario(); - void WriteBehavior(); - void WriteViewer(); - void WriteStartPositions(); - - void UpdateEdges(); - void UpdateObstacles(); - void UpdateNodes(); - - void Test(); - - const std::vector<NavMesh::JEdge*>& GetEdges() const; - const std::vector<NavMesh::JNode*>& GetNodes() const; - const std::vector<NavMesh::JObstacle*>& GetObst() const; - const std::vector<NavMesh::JVertex*>& GetVertices() const; + bool operator< (const JVertex& v) const { + return v.pPos._x<pPos._x; + } + bool operator> (const JVertex& v) const { + return v.pPos._x>pPos._x; + } + + }; + + class JNode { + public: + std::string pGroup; + Point pCentroid; + int id; + std::vector<JVertex> pHull; + std::vector<int> pObstacles; + std::vector<int> pPortals; + double pNormalVec[3]; + + bool operator()(JNode*a ,JNode* b) { + return a->pGroup < b->pGroup; + } + + bool operator==(const JNode& other) { + + if(pCentroid!=other.pCentroid) return false; + if(pObstacles.size()!=other.pObstacles.size()) return false; + if(pPortals.size()!=other.pPortals.size()) return false; + + + // the obstacles and the portals are sorted + for(unsigned int s=0; s<pPortals.size(); s++) { + if(pPortals[s]!=other.pPortals[s]) return false; + } + for(unsigned int s=0; s<pObstacles.size(); s++) { + if(pObstacles[s]!=other.pObstacles[s]) return false; + } + return true; + } + + ///http://stackoverflow.com/questions/471962/how-do-determine-if-a-polygon-is-complex-convex-nonconvex + bool IsConvex() { + + unsigned int hsize=pHull.size(); + unsigned int pos=0; + unsigned int neg=0; + + for(unsigned int i=0; i<hsize; i++) { + Point vecAB= pHull[(i+1)%hsize].pPos-pHull[i%hsize].pPos; + Point vecBC= pHull[(i+2)%hsize].pPos-pHull[(i+1)%hsize].pPos; + double det= vecAB.Det(vecBC); + if(fabs(det)<J_EPS) det=0.0; + + if(det<0.0) { + neg++; + } else if(det>0.0) { + pos++; + } else { + pos++; + neg++; + } + + } + + if ( (pos==hsize ) || (neg==hsize) ) { + return true; + } + return false; + } + + ///http://stackoverflow.com/questions/9473570/polygon-vertices-clockwise-or-counterclockwise/ + bool IsClockwise() { + if(pHull.size()<3) { + std::cerr<<"You need at least 3 vertices. JNode ID ["<<id<<" ]"<<std::endl; + exit(EXIT_FAILURE); + } + + Point vecAB= pHull[1].pPos-pHull[0].pPos; + Point vecBC= pHull[2].pPos-pHull[1].pPos; + + double det=vecAB.Det(vecBC); + if(fabs(det)<J_EPS) det=0.0; + + return ( det<=0.0 ); + } + + + }; + + class JEdge { + public: + int id; + JVertex pStart; + JVertex pEnd; + //Point pDisp; + int pNode0; + int pNode1; + JEdge() { + id=-1; + pNode0=-1; + pNode1=-1; + } + }; + + class JObstacle { + public: + int id; + JVertex pStart; + JVertex pEnd; + //Point pDisp; + int pNode0; + int pNextObst; + + int GetCommonVertex(JObstacle* obst) { + if(obst->pEnd.id==pEnd.id) return pEnd.id; + if(obst->pEnd.id==pStart.id) return pStart.id; + if(obst->pStart.id==pStart.id) return pStart.id; + if(obst->pStart.id==pEnd.id) return pEnd.id; + return -1; + } + }; + + + + template<typename A> + bool IsElementInVector(const std::vector<A> &vec, A& el) { + typename std::vector<A>::const_iterator it; + it = std::find (vec.begin(), vec.end(), el); + if(it==vec.end()) { + return false; + } else { + return true; + } + } + + +private: + std::vector<JVertex*> _vertices; + std::vector<JEdge*> _edges; + std::vector<JObstacle*> _obst; + std::vector<JNode*> _nodes; + Building* _building; + + std::vector<JNode*> new_nodes; + std::vector<int> problem_nodes; + + //this is used for subroom with obstacles + std::map<int, std::pair<int,int> > map_node_to_subroom; + + // Check the created navmesh for convex polygons + // convexify the created nav mesh + void Convexify(); + + // Add the additional surrounding world JObstacle + // and triangulate + void Finalize(); + + void FinalizeAlphaShape(); + + /** + * @return true if there is a visibility line between the segment and a portion of the circle + */ + bool IsCircleVisibleFromLine(const Point& center, double radius, const Line& segment); + + void ComputePlaneEquation(SubRoom* sub, double* coefficents); + + void ComputeStairsEquation(); + void ComputePlanesEquation(); + + // Triangulate a subroom possibly with obstacles + void Triangulate(SubRoom* sub); + void Triangulate(JNode* JNode); + + /// Return the id of the JEdge + int IsPortal(Point& p1, Point& p2); + /// Return the id of the JObstacle + int IsObstacle(Point& p1, Point& p2); + + +public: + + NavMesh(Building* b); + virtual ~NavMesh(); + void BuildNavMesh(); + void WriteToFile(std::string fileName); + void WriteToString(std::string& output); + void WriteToFileTraVisTo(std::string fileName); + void WriteToFileTraVisTo(std::string fileName, const std::vector<Point>& points); + void WriteToFileTraVisTo(std::string fileName, JNode* node); + + int AddVertex(JVertex* v); + int AddEdge(JEdge* e); + int AddObst(JObstacle* o); + int AddNode(JNode* n); + + ///return the JVertex with the corresponding point + JVertex* GetVertex(const Point& p); + void DumpNode(int id); + void DumpEdge(int id); + void DumpObstacle(int id); + + /// Write the simulation scenario for the + /// pedunc simulator + void WriteScenario(); + void WriteBehavior(); + void WriteViewer(); + void WriteStartPositions(); + + void UpdateEdges(); + void UpdateObstacles(); + void UpdateNodes(); + + void Test(); + + const std::vector<NavMesh::JEdge*>& GetEdges() const; + const std::vector<NavMesh::JNode*>& GetNodes() const; + const std::vector<NavMesh::JObstacle*>& GetObst() const; + const std::vector<NavMesh::JVertex*>& GetVertices() const; - // need to access vertices and nodes - friend class TrajectoriesVTK; + // need to access vertices and nodes + friend class TrajectoriesVTK; }; diff --git a/routing/QuickestPathRouter.cpp b/routing/QuickestPathRouter.cpp index aab9c497d53e9edce9e7e8a5579c02e8795f565f..9f6e7b5dd241313f61d1b1e756af8f1288706ca9 100644 --- a/routing/QuickestPathRouter.cpp +++ b/routing/QuickestPathRouter.cpp @@ -41,258 +41,260 @@ QuickestPathRouter::QuickestPathRouter( ):GlobalRouter() { } QuickestPathRouter::~QuickestPathRouter() { } -string QuickestPathRouter::GetRoutingInfoFile() const { +string QuickestPathRouter::GetRoutingInfoFile() const +{ - TiXmlDocument doc(_building->GetProjectFilename()); - if (!doc.LoadFile()){ - Log->Write("ERROR: \t%s", doc.ErrorDesc()); - Log->Write("ERROR: \t could not open/parse the project file"); - exit(EXIT_FAILURE); - } + TiXmlDocument doc(_building->GetProjectFilename()); + if (!doc.LoadFile()) { + Log->Write("ERROR: \t%s", doc.ErrorDesc()); + Log->Write("ERROR: \t could not open/parse the project file"); + exit(EXIT_FAILURE); + } - // everything is fine. proceed with parsing - TiXmlElement* xMainNode = doc.RootElement(); - TiXmlNode* xRouters=xMainNode->FirstChild("route_choice_models"); + // everything is fine. proceed with parsing + TiXmlElement* xMainNode = doc.RootElement(); + TiXmlNode* xRouters=xMainNode->FirstChild("route_choice_models"); - string nav_line_file=""; + string nav_line_file=""; - for(TiXmlElement* e = xRouters->FirstChildElement("router"); e; - e = e->NextSiblingElement("router")) { + for(TiXmlElement* e = xRouters->FirstChildElement("router"); e; + e = e->NextSiblingElement("router")) { - string strategy=e->Attribute("description"); + string strategy=e->Attribute("description"); - if(strategy=="quickest"){ - if (e->FirstChild("parameters")->FirstChildElement("navigation_lines")) - nav_line_file=e->FirstChild("parameters")->FirstChildElement("navigation_lines")->Attribute("file"); - } - } - return _building->GetProjectRootDir()+nav_line_file; + if(strategy=="quickest") { + if (e->FirstChild("parameters")->FirstChildElement("navigation_lines")) + nav_line_file=e->FirstChild("parameters")->FirstChildElement("navigation_lines")->Attribute("file"); + } + } + return _building->GetProjectRootDir()+nav_line_file; } -int QuickestPathRouter::FindExit(Pedestrian* ped){ +int QuickestPathRouter::FindExit(Pedestrian* ped) +{ - int next=FindNextExit(ped); + int next=FindNextExit(ped); - // that ped will be deleted - if(next==-1) return next; + // that ped will be deleted + if(next==-1) return next; - if(ped->IsFeelingLikeInJam()){ - //ped->SetSpotlight(true); + if(ped->IsFeelingLikeInJam()) { + //ped->SetSpotlight(true); - if(isCongested(ped)==true){ - Redirect(ped); - ped->ResetTimeInJam(); - ped->SetSpotlight(true); - } - //cout<<"I am feeling like in Jam next: "<<ped->GetID()<<endl; - //ped->RerouteIn(2.50); // seconds - }else if(ped->IsReadyForRerouting()){ - Redirect(ped); - ped->ResetRerouting(); + if(isCongested(ped)==true) { + Redirect(ped); + ped->ResetTimeInJam(); + ped->SetSpotlight(true); + } + //cout<<"I am feeling like in Jam next: "<<ped->GetID()<<endl; + //ped->RerouteIn(2.50); // seconds + } else if(ped->IsReadyForRerouting()) { + Redirect(ped); + ped->ResetRerouting(); - }else{ - ped->UpdateReroutingTime(); - } + } else { + ped->UpdateReroutingTime(); + } - return next; + return next; } -int QuickestPathRouter::FindNextExit(Pedestrian* ped){ - - - int nextDestination = ped->GetNextDestination(); - //ped->Dump(1); - - if (nextDestination == -1) { - return GetBestDefaultRandomExit(ped); - - } else { - - SubRoom* sub = _building->GetRoom(ped->GetRoomID())->GetSubRoom( - ped->GetSubRoomID()); - - const vector<int>& accessPointsInSubRoom = sub->GetAllGoalIDs(); - for (unsigned int i = 0; i < accessPointsInSubRoom.size(); i++) { - - int apID = accessPointsInSubRoom[i]; - AccessPoint* ap = _accessPoints[apID]; - - const Point& pt3 = ped->GetPos(); - double distToExit = ap->GetNavLine()->DistTo(pt3); - - if (distToExit > J_EPS_DIST) - continue; - - nextDestination = GetQuickestRoute(ped,_accessPoints[apID]); - - //uncomment these lines to return to the gsp - //nextDestination = ap->GetNearestTransitAPTO(ped->GetFinalDestination()); - - if (nextDestination == -1) { // we are almost at the exit - return ped->GetNextDestination(); - } else { - //check that the next destination is in the actual room of the pedestrian - if (_accessPoints[nextDestination]->isInRange( - sub->GetUID())==false) { - //return the last destination if defined - int previousDestination = ped->GetNextDestination(); - - //we are still somewhere in the initialization phase - if (previousDestination == -1) { - ped->SetExitIndex(apID); - ped->SetExitLine(_accessPoints[apID]->GetNavLine()); - //ped->SetSmoothTurning(true); - - return apID; - } - else // we are still having a valid destination, don't change - { - return previousDestination; - } - } - else // we have reached the new room - { - ped->SetExitIndex(nextDestination); - ped->SetExitLine( - _accessPoints[nextDestination]->GetNavLine()); - //ped->SetSmoothTurning(true); - return nextDestination; - } - } - } - - // still have a valid destination, so return it - return nextDestination; - } +int QuickestPathRouter::FindNextExit(Pedestrian* ped) +{ + + + int nextDestination = ped->GetNextDestination(); + //ped->Dump(1); + + if (nextDestination == -1) { + return GetBestDefaultRandomExit(ped); + + } else { + + SubRoom* sub = _building->GetRoom(ped->GetRoomID())->GetSubRoom( + ped->GetSubRoomID()); + + const vector<int>& accessPointsInSubRoom = sub->GetAllGoalIDs(); + for (unsigned int i = 0; i < accessPointsInSubRoom.size(); i++) { + + int apID = accessPointsInSubRoom[i]; + AccessPoint* ap = _accessPoints[apID]; + + const Point& pt3 = ped->GetPos(); + double distToExit = ap->GetNavLine()->DistTo(pt3); + + if (distToExit > J_EPS_DIST) + continue; + + nextDestination = GetQuickestRoute(ped,_accessPoints[apID]); + + //uncomment these lines to return to the gsp + //nextDestination = ap->GetNearestTransitAPTO(ped->GetFinalDestination()); + + if (nextDestination == -1) { // we are almost at the exit + return ped->GetNextDestination(); + } else { + //check that the next destination is in the actual room of the pedestrian + if (_accessPoints[nextDestination]->isInRange( + sub->GetUID())==false) { + //return the last destination if defined + int previousDestination = ped->GetNextDestination(); + + //we are still somewhere in the initialization phase + if (previousDestination == -1) { + ped->SetExitIndex(apID); + ped->SetExitLine(_accessPoints[apID]->GetNavLine()); + //ped->SetSmoothTurning(true); + + return apID; + } else { // we are still having a valid destination, don't change + return previousDestination; + } + } else { // we have reached the new room + ped->SetExitIndex(nextDestination); + ped->SetExitLine( + _accessPoints[nextDestination]->GetNavLine()); + //ped->SetSmoothTurning(true); + return nextDestination; + } + } + } + + // still have a valid destination, so return it + return nextDestination; + } } -double QuickestPathRouter::CBA (double ref_g1, double comp_g2){ - return (comp_g2-ref_g1)/(ref_g1+comp_g2); +double QuickestPathRouter::CBA (double ref_g1, double comp_g2) +{ + return (comp_g2-ref_g1)/(ref_g1+comp_g2); } -double QuickestPathRouter::TAP (double alpha){ - alpha=fabs(alpha); - const double pi = 3.14159265; - - if(alpha<(pi/3.0)){ - return 0.9; - } - else if((alpha>=(pi/3.0))&&(alpha<(2*pi/3.0))){ - return 0.8; - }else{ - return 0.7; - } - // return ( (alpha < pi/3 )? (0.9):( (alpha<2*pi/3) ? (0.8):(0.9)) ); - return 1; +double QuickestPathRouter::TAP (double alpha) +{ + alpha=fabs(alpha); + const double pi = 3.14159265; + + if(alpha<(pi/3.0)) { + return 0.9; + } else if((alpha>=(pi/3.0))&&(alpha<(2*pi/3.0))) { + return 0.8; + } else { + return 0.7; + } + // return ( (alpha < pi/3 )? (0.9):( (alpha<2*pi/3) ? (0.8):(0.9)) ); + return 1; } -int QuickestPathRouter::GetQuickestRoute(Pedestrian*ped, AccessPoint* nearestAP){ +int QuickestPathRouter::GetQuickestRoute(Pedestrian*ped, AccessPoint* nearestAP) +{ - int preferredExit=nearestAP->GetNearestTransitAPTO(ped->GetFinalDestination()); - double preferredExitTime=FLT_MAX; - int quickest=-1; - double minTime=FLT_MAX; + int preferredExit=nearestAP->GetNearestTransitAPTO(ped->GetFinalDestination()); + double preferredExitTime=FLT_MAX; + int quickest=-1; + double minTime=FLT_MAX; - // get all AP connected to the nearest - //const vector<AccessPoint*>& aps = nearestAP->GetConnectingAPs(); + // get all AP connected to the nearest + //const vector<AccessPoint*>& aps = nearestAP->GetConnectingAPs(); - //TODO: should be get relevant destination - const vector<AccessPoint*>& aps = nearestAP->GetTransitAPsTo(ped->GetFinalDestination()); + //TODO: should be get relevant destination + const vector<AccessPoint*>& aps = nearestAP->GetTransitAPsTo(ped->GetFinalDestination()); - //special case where there is only one alternative - if(aps.size()==1) return preferredExit; + //special case where there is only one alternative + if(aps.size()==1) return preferredExit; - //TODO: what happens to hlines? - // this can be mitigated with a floor field + //TODO: what happens to hlines? + // this can be mitigated with a floor field - //select the optimal time - for(unsigned int ap=0;ap<aps.size();ap++){ + //select the optimal time + for(unsigned int ap=0; ap<aps.size(); ap++) { - // select the reference and - int flag=0; - int exitid=aps[ap]->GetID(); - Pedestrian* myref=NULL; - SelectReferencePedestrian(ped,&myref,J_QUEUE_VEL_THRESHOLD_NEW_ROOM,exitid,&flag); + // select the reference and + int flag=0; + int exitid=aps[ap]->GetID(); + Pedestrian* myref=NULL; + SelectReferencePedestrian(ped,&myref,J_QUEUE_VEL_THRESHOLD_NEW_ROOM,exitid,&flag); - // compute the time - double time=FLT_MAX; + // compute the time + double time=FLT_MAX; - // case of free exit - if((myref==NULL)&& (flag==FREE_EXIT)){ - //time= (ped->GetPos()- aps[ap]->GetCentre()).Norm()/ped->GetV0Norm(); - // time to reach the AP - double t1 = (ped->GetPos()- aps[ap]->GetCentre()).Norm()/ped->GetV().Norm(); + // case of free exit + if((myref==NULL)&& (flag==FREE_EXIT)) { + //time= (ped->GetPos()- aps[ap]->GetCentre()).Norm()/ped->GetV0Norm(); + // time to reach the AP + double t1 = (ped->GetPos()- aps[ap]->GetCentre()).Norm()/ped->GetV().Norm(); - //guess time from the Ap to the outside - double t2 = (aps[ap]->GetDistanceTo(ped->GetFinalDestination()))/ped->GetV().Norm(); + //guess time from the Ap to the outside + double t2 = (aps[ap]->GetDistanceTo(ped->GetFinalDestination()))/ped->GetV().Norm(); - time=t1+t2; - //cout<<"time = "<<time<<endl; - } + time=t1+t2; + //cout<<"time = "<<time<<endl; + } - // case of unreachable exit - if((myref==NULL)&& (flag==UNREACHEABLE_EXIT)){ - time= FLT_MAX; - } + // case of unreachable exit + if((myref==NULL)&& (flag==UNREACHEABLE_EXIT)) { + time= FLT_MAX; + } - // case of ref ped - if((myref!=NULL) && (flag==REF_PED_FOUND)){ + // case of ref ped + if((myref!=NULL) && (flag==REF_PED_FOUND)) { - //time to reach the reference - double t1= (ped->GetPos()- myref->GetPos()).Norm()/ped->GetV().Norm(); - //double t1= (ped->GetPos()- myref->GetPos()).Norm()/ped->GetV0Norm(); + //time to reach the reference + double t1= (ped->GetPos()- myref->GetPos()).Norm()/ped->GetV().Norm(); + //double t1= (ped->GetPos()- myref->GetPos()).Norm()/ped->GetV0Norm(); - //if(myref->GetV().Norm()==0.0){ - // cout<<"bye"<<endl; exit(0); - //} - //time for the reference to get out - double t2=(myref->GetPos()- aps[ap]->GetCentre()).Norm()/myref->GetV().Norm(); + //if(myref->GetV().Norm()==0.0){ + // cout<<"bye"<<endl; exit(0); + //} + //time for the reference to get out + double t2=(myref->GetPos()- aps[ap]->GetCentre()).Norm()/myref->GetV().Norm(); - //guess time from the Ap to the outside - double t3 = (aps[ap]->GetDistanceTo(ped->GetFinalDestination()))/ped->GetV().Norm(); + //guess time from the Ap to the outside + double t3 = (aps[ap]->GetDistanceTo(ped->GetFinalDestination()))/ped->GetV().Norm(); - time=t1+t2+t3; - } + time=t1+t2+t3; + } - if((myref==NULL) && (flag==REF_PED_FOUND)){ - Log->Write("ERROR:\t Fatal Error in Quickest Path Router"); - Log->Write("ERROR:\t reference pedestrians is NULL"); - exit(EXIT_FAILURE); - } + if((myref==NULL) && (flag==REF_PED_FOUND)) { + Log->Write("ERROR:\t Fatal Error in Quickest Path Router"); + Log->Write("ERROR:\t reference pedestrians is NULL"); + exit(EXIT_FAILURE); + } - if(time<minTime){ - minTime=time; - quickest=exitid; - } + if(time<minTime) { + minTime=time; + quickest=exitid; + } - //printf(" ped [%d] checking [%d] ---> [%f]\n",ped->GetPedIndex(),exitid,time); - //also save the time for the default destinations for later comparison - if (exitid==preferredExit){ - preferredExitTime=time; - } + //printf(" ped [%d] checking [%d] ---> [%f]\n",ped->GetPedIndex(),exitid,time); + //also save the time for the default destinations for later comparison + if (exitid==preferredExit) { + preferredExitTime=time; + } - //if(ped->GetPedIndex()==27){ - // printf("reference to exit [%d] is ped [%d]\n",exitid,myref->GetPedIndex()); - //} - } - //compare it with my preferred (shortest nearest) - if(quickest==preferredExit) return quickest; + //if(ped->GetPedIndex()==27){ + // printf("reference to exit [%d] is ped [%d]\n",exitid,myref->GetPedIndex()); + //} + } + //compare it with my preferred (shortest nearest) + if(quickest==preferredExit) return quickest; - double cba = CBA(gain(preferredExitTime),gain(minTime)); + double cba = CBA(gain(preferredExitTime),gain(minTime)); - //cout<<"cba:" <<cba<<endl; - if (cba<CBA_THRESHOLD) return preferredExit; + //cout<<"cba:" <<cba<<endl; + if (cba<CBA_THRESHOLD) return preferredExit; - return quickest; + return quickest; } -double QuickestPathRouter::gain(double time){ - return 1.0/time; +double QuickestPathRouter::gain(double time) +{ + return 1.0/time; } @@ -376,669 +378,680 @@ double QuickestPathRouter::gain(double time){ //} -void QuickestPathRouter::ReduceGraph(){ +void QuickestPathRouter::ReduceGraph() +{ - for(unsigned int i=0;i<_accessPoints.size();i++){ - vector<AccessPoint*>toBeDeleted; - AccessPoint* from_AP=_accessPoints[i]; - int from_door=from_AP->GetID(); + for(unsigned int i=0; i<_accessPoints.size(); i++) { + vector<AccessPoint*>toBeDeleted; + AccessPoint* from_AP=_accessPoints[i]; + int from_door=from_AP->GetID(); - // get all AP connected to the nearest - const vector<AccessPoint*>& aps = from_AP->GetConnectingAPs(); + // get all AP connected to the nearest + const vector<AccessPoint*>& aps = from_AP->GetConnectingAPs(); - //loop over all accesspoint connections and - //collect the connections to remove + //loop over all accesspoint connections and + //collect the connections to remove - for(unsigned int j=0;j<aps.size();j++) - { - AccessPoint* to_AP=aps[j]; + for(unsigned int j=0; j<aps.size(); j++) { + AccessPoint* to_AP=aps[j]; - /* TODO: check all final destinations - for( map<int, int>::iterator it = pMapIdToFinalDestination.begin(); - it != pMapIdToFinalDestination.end(); it++) { - int fid=it->first; - */ + /* TODO: check all final destinations + for( map<int, int>::iterator it = pMapIdToFinalDestination.begin(); + it != pMapIdToFinalDestination.end(); it++) { + int fid=it->first; + */ - //remove all AP which point to me - if(to_AP->GetNearestTransitAPTO(FINAL_DEST_OUT)==from_door){ - toBeDeleted.push_back(to_AP); - } + //remove all AP which point to me + if(to_AP->GetNearestTransitAPTO(FINAL_DEST_OUT)==from_door) { + toBeDeleted.push_back(to_AP); + } - //don't remove if that is the best destination - //TODO: if there are more suitable final destinations? - if(GetCommonDestinationCount(from_AP, to_AP)>0){ - if(from_AP->GetNearestTransitAPTO(FINAL_DEST_OUT)!=to_AP->GetID()) - toBeDeleted.push_back(to_AP); - } + //don't remove if that is the best destination + //TODO: if there are more suitable final destinations? + if(GetCommonDestinationCount(from_AP, to_AP)>0) { + if(from_AP->GetNearestTransitAPTO(FINAL_DEST_OUT)!=to_AP->GetID()) + toBeDeleted.push_back(to_AP); + } - // remove all APs wich have at least one common destination with me - // if (to_AP->GetNextApTo(FINAL_DEST_OUT)==from_AP->GetNextApTo(FINAL_DEST_OUT)) { - // toBeDeleted.push_back(to_AP); - // - // } - } + // remove all APs wich have at least one common destination with me + // if (to_AP->GetNextApTo(FINAL_DEST_OUT)==from_AP->GetNextApTo(FINAL_DEST_OUT)) { + // toBeDeleted.push_back(to_AP); + // + // } + } - // now remove the aps/connections - std::sort(toBeDeleted.begin(), toBeDeleted.end()); - toBeDeleted.erase(std::unique(toBeDeleted.begin(), toBeDeleted.end()), toBeDeleted.end()); - for(unsigned int k=0;k<toBeDeleted.size();k++){ - from_AP->RemoveConnectingAP(toBeDeleted[k]); - } - } + // now remove the aps/connections + std::sort(toBeDeleted.begin(), toBeDeleted.end()); + toBeDeleted.erase(std::unique(toBeDeleted.begin(), toBeDeleted.end()), toBeDeleted.end()); + for(unsigned int k=0; k<toBeDeleted.size(); k++) { + from_AP->RemoveConnectingAP(toBeDeleted[k]); + } + } - //clear double links - CheckAndClearDoubleLinkedNodes(); + //clear double links + CheckAndClearDoubleLinkedNodes(); } -void QuickestPathRouter::CheckAndClearDoubleLinkedNodes(){ - - for(unsigned int i=0;i<_accessPoints.size();i++){ - vector<AccessPoint*>toBeDeleted; - AccessPoint* from_AP=_accessPoints[i]; - const vector<AccessPoint*>& from_aps = from_AP->GetConnectingAPs(); - - for(unsigned int j=0;j<_accessPoints.size();j++){ - AccessPoint* to_AP=_accessPoints[j]; - const vector<AccessPoint*>& to_aps = to_AP->GetConnectingAPs(); - - // if one contains the other - if(IsElementInVector(from_aps,to_AP)&&IsElementInVector(to_aps,from_AP)){ - //check the distances - double dist1=from_AP->GetDistanceTo(to_AP) +to_AP->GetDistanceTo(FINAL_DEST_OUT); - double dist2=to_AP->GetDistanceTo(from_AP) +from_AP->GetDistanceTo(FINAL_DEST_OUT); - if(dist1<dist2){ - to_AP->RemoveConnectingAP(from_AP); - }else{ - from_AP->RemoveConnectingAP(to_AP); - } - } - } - } +void QuickestPathRouter::CheckAndClearDoubleLinkedNodes() +{ + + for(unsigned int i=0; i<_accessPoints.size(); i++) { + vector<AccessPoint*>toBeDeleted; + AccessPoint* from_AP=_accessPoints[i]; + const vector<AccessPoint*>& from_aps = from_AP->GetConnectingAPs(); + + for(unsigned int j=0; j<_accessPoints.size(); j++) { + AccessPoint* to_AP=_accessPoints[j]; + const vector<AccessPoint*>& to_aps = to_AP->GetConnectingAPs(); + + // if one contains the other + if(IsElementInVector(from_aps,to_AP)&&IsElementInVector(to_aps,from_AP)) { + //check the distances + double dist1=from_AP->GetDistanceTo(to_AP) +to_AP->GetDistanceTo(FINAL_DEST_OUT); + double dist2=to_AP->GetDistanceTo(from_AP) +from_AP->GetDistanceTo(FINAL_DEST_OUT); + if(dist1<dist2) { + to_AP->RemoveConnectingAP(from_AP); + } else { + from_AP->RemoveConnectingAP(to_AP); + } + } + } + } } -void QuickestPathRouter::ExpandGraph(){ - - for(unsigned int i=0;i<_accessPoints.size();i++){ - vector<AccessPoint*>toBeDeleted; - AccessPoint* tmp=_accessPoints[i]; - - // get all AP connected to the nearest - const vector<AccessPoint*>& aps = tmp->GetConnectingAPs(); - - //loop over all accesspoint connections and - //collect the connections to remove - - for(unsigned int j=0;j<aps.size();j++) - { - AccessPoint* tmp1=aps[j]; - - if(tmp->GetNearestTransitAPTO(FINAL_DEST_OUT)==tmp1->GetNearestTransitAPTO(FINAL_DEST_OUT)) - toBeDeleted.push_back(tmp1); - if(tmp->GetID()==tmp1->GetNearestTransitAPTO(FINAL_DEST_OUT)) - toBeDeleted.push_back(tmp1); - if(tmp1->GetDistanceTo(FINAL_DEST_OUT)>tmp->GetDistanceTo(FINAL_DEST_OUT)) - toBeDeleted.push_back(tmp1); - - int bestID=tmp1->GetNearestTransitAPTO(FINAL_DEST_OUT); - double dist1=_accessPoints[bestID]->GetDistanceTo(tmp)+tmp->GetDistanceTo(tmp1); - double dist2=tmp->GetDistanceTo(tmp1); - if(dist1<dist2) - toBeDeleted.push_back(tmp1); - - // for(unsigned int l=0;l<aps.size();l++) - // { - // AccessPoint* tmp2=aps[l]; - // if(tmp2->GetID()==tmp1->GetID())continue; - // - // const vector<AccessPoint*>& aps1 = tmp1->GetConnectingAPs(); - // for(unsigned int k=0;k<aps1.size();k++) - // { - // AccessPoint* tmp3=aps1[k]; - // if(tmp3->GetID()==tmp2->GetID()){ - // toBeDeleted.push_back(tmp1); - // } - // } - // } - } - - // now remove the aps/connections - for(unsigned int k=0;k<toBeDeleted.size();k++){ - tmp->RemoveConnectingAP(toBeDeleted[k]); - } - - } +void QuickestPathRouter::ExpandGraph() +{ + + for(unsigned int i=0; i<_accessPoints.size(); i++) { + vector<AccessPoint*>toBeDeleted; + AccessPoint* tmp=_accessPoints[i]; + + // get all AP connected to the nearest + const vector<AccessPoint*>& aps = tmp->GetConnectingAPs(); + + //loop over all accesspoint connections and + //collect the connections to remove + + for(unsigned int j=0; j<aps.size(); j++) { + AccessPoint* tmp1=aps[j]; + + if(tmp->GetNearestTransitAPTO(FINAL_DEST_OUT)==tmp1->GetNearestTransitAPTO(FINAL_DEST_OUT)) + toBeDeleted.push_back(tmp1); + if(tmp->GetID()==tmp1->GetNearestTransitAPTO(FINAL_DEST_OUT)) + toBeDeleted.push_back(tmp1); + if(tmp1->GetDistanceTo(FINAL_DEST_OUT)>tmp->GetDistanceTo(FINAL_DEST_OUT)) + toBeDeleted.push_back(tmp1); + + int bestID=tmp1->GetNearestTransitAPTO(FINAL_DEST_OUT); + double dist1=_accessPoints[bestID]->GetDistanceTo(tmp)+tmp->GetDistanceTo(tmp1); + double dist2=tmp->GetDistanceTo(tmp1); + if(dist1<dist2) + toBeDeleted.push_back(tmp1); + + // for(unsigned int l=0;l<aps.size();l++) + // { + // AccessPoint* tmp2=aps[l]; + // if(tmp2->GetID()==tmp1->GetID())continue; + // + // const vector<AccessPoint*>& aps1 = tmp1->GetConnectingAPs(); + // for(unsigned int k=0;k<aps1.size();k++) + // { + // AccessPoint* tmp3=aps1[k]; + // if(tmp3->GetID()==tmp2->GetID()){ + // toBeDeleted.push_back(tmp1); + // } + // } + // } + } + + // now remove the aps/connections + for(unsigned int k=0; k<toBeDeleted.size(); k++) { + tmp->RemoveConnectingAP(toBeDeleted[k]); + } + + } } -void QuickestPathRouter::Init(Building* building){ +void QuickestPathRouter::Init(Building* building) +{ - Log->Write("INFO:\tInit Quickest Path Router Engine"); - GlobalRouter::Init(building); + Log->Write("INFO:\tInit Quickest Path Router Engine"); + GlobalRouter::Init(building); - // activate the spotlight for tracking some pedestrians - Pedestrian::ActivateSpotlightSystem(true); + // activate the spotlight for tracking some pedestrians + Pedestrian::ActivateSpotlightSystem(true); - // pBuilding=building; - //TODO: reduce graph is missbehaving - //ReduceGraph(); - //ExpandGraph(); - //vector<string> rooms; - //rooms.push_back("150"); - //rooms.push_back("outside"); - //WriteGraphGV("routing_graph.gv",FINAL_DEST_ROOM_040,rooms); - //WriteGraphGV("routing_graph.gv",FINAL_DEST_OUT,rooms); - //DumpAccessPoints(1185); + // pBuilding=building; + //TODO: reduce graph is missbehaving + //ReduceGraph(); + //ExpandGraph(); + //vector<string> rooms; + //rooms.push_back("150"); + //rooms.push_back("outside"); + //WriteGraphGV("routing_graph.gv",FINAL_DEST_ROOM_040,rooms); + //WriteGraphGV("routing_graph.gv",FINAL_DEST_OUT,rooms); + //DumpAccessPoints(1185); - // exit(0); - Log->Write("INFO:\tDone with Quickest Path Router Engine!"); + // exit(0); + Log->Write("INFO:\tDone with Quickest Path Router Engine!"); } -void QuickestPathRouter::SelectReferencePedestrian(Pedestrian* myself, Pedestrian** myref, double jamThreshold, int exitID, int* flag){ - - *flag=FREE_EXIT; // assume free exit - - Crossing* crossing=_building->GetTransOrCrossByUID(exitID); - - - double radius=3.0;//start radius for looking at the reference in metres - bool done=false; - - do{ - vector<Pedestrian*> queue; - queue.reserve(250); - GetQueueAtExit(crossing,jamThreshold,radius,queue,myself->GetSubRoomID()); - if(queue.size()==0){ - //check if I can see/reach the exit without much effort - if(IsDirectVisibilityBetween(myself,crossing)){ - *myref=NULL; - *flag=FREE_EXIT; - }else{ - *myref=NULL; - *flag=UNREACHEABLE_EXIT; - } - // we should return here as there is no queue - done=true; - - }else{ - - double closestDistance=FLT_MAX; - //select a reference pedestrian I can see - for(unsigned int p=0;p<queue.size();p++){ - Pedestrian* ped = queue[p]; //ped->SetSpotlight(true); - if(IsDirectVisibilityBetween(myself,ped)==false) continue; - double dist= (ped->GetPos()-myself->GetPos()).NormSquare(); - //cout<<"suspect found 1 @ "<< dist<< " { "<< closestDistance<<" }"<<endl; - if(dist<closestDistance){ - closestDistance=dist; - *myref=ped; - *flag=REF_PED_FOUND; // at least one reference was found - done=true; - } - } - } - - // we could not find any visible reference so far, we widen our sight range - // and to the same again - radius=radius*2; - if(radius>100){ - if(queue.size()>0){ // there were some ref pedes only not visibles - *myref=NULL; - *flag=UNREACHEABLE_EXIT; - done=true; - - }else{ - *myref=NULL; - *flag=UNREACHEABLE_EXIT; - done=true; - - Log->Write("ERROR: reference ped cannot be found for ped %d within [%f] m around the exit [%d]\n",myself->GetID(),radius,crossing->GetID()); - exit(EXIT_FAILURE); - } - } - - /////delete me after - // if(done==true){ - // //debug area - // if(*myref){ - // - // if(myself->GetID()==488){ - // myself->SetSpotlight(true); - // (*myref)->SetSpotlight(true); - // (*myref)->Dump((*myref)->GetID()); - // - // //highlight the queue - // for(unsigned int p=0;p<queue.size();p++){ - // Pedestrian* ped = queue[p]; - // ped->SetSpotlight(true); - // } - // - // } - // } - // } - //// delete me after - } while (done==false); - - - //debug area - if(*myref){ - - // if(myself->GetID()==488){ - // myself->SetSpotlight(true); - // (*myref)->SetSpotlight(true); - // (*myref)->Dump((*myref)->GetID()); - // - // - // } - - } - else{ - //cout<<"no ref ped found: " <<endl; - //getc(stdin); - } +void QuickestPathRouter::SelectReferencePedestrian(Pedestrian* myself, Pedestrian** myref, double jamThreshold, int exitID, int* flag) +{ + + *flag=FREE_EXIT; // assume free exit + + Crossing* crossing=_building->GetTransOrCrossByUID(exitID); + + + double radius=3.0;//start radius for looking at the reference in metres + bool done=false; + + do { + vector<Pedestrian*> queue; + queue.reserve(250); + GetQueueAtExit(crossing,jamThreshold,radius,queue,myself->GetSubRoomID()); + if(queue.size()==0) { + //check if I can see/reach the exit without much effort + if(IsDirectVisibilityBetween(myself,crossing)) { + *myref=NULL; + *flag=FREE_EXIT; + } else { + *myref=NULL; + *flag=UNREACHEABLE_EXIT; + } + // we should return here as there is no queue + done=true; + + } else { + + double closestDistance=FLT_MAX; + //select a reference pedestrian I can see + for(unsigned int p=0; p<queue.size(); p++) { + Pedestrian* ped = queue[p]; //ped->SetSpotlight(true); + if(IsDirectVisibilityBetween(myself,ped)==false) continue; + double dist= (ped->GetPos()-myself->GetPos()).NormSquare(); + //cout<<"suspect found 1 @ "<< dist<< " { "<< closestDistance<<" }"<<endl; + if(dist<closestDistance) { + closestDistance=dist; + *myref=ped; + *flag=REF_PED_FOUND; // at least one reference was found + done=true; + } + } + } + + // we could not find any visible reference so far, we widen our sight range + // and to the same again + radius=radius*2; + if(radius>100) { + if(queue.size()>0) { // there were some ref pedes only not visibles + *myref=NULL; + *flag=UNREACHEABLE_EXIT; + done=true; + + } else { + *myref=NULL; + *flag=UNREACHEABLE_EXIT; + done=true; + + Log->Write("ERROR: reference ped cannot be found for ped %d within [%f] m around the exit [%d]\n",myself->GetID(),radius,crossing->GetID()); + exit(EXIT_FAILURE); + } + } + + /////delete me after + // if(done==true){ + // //debug area + // if(*myref){ + // + // if(myself->GetID()==488){ + // myself->SetSpotlight(true); + // (*myref)->SetSpotlight(true); + // (*myref)->Dump((*myref)->GetID()); + // + // //highlight the queue + // for(unsigned int p=0;p<queue.size();p++){ + // Pedestrian* ped = queue[p]; + // ped->SetSpotlight(true); + // } + // + // } + // } + // } + //// delete me after + } while (done==false); + + + //debug area + if(*myref) { + + // if(myself->GetID()==488){ + // myself->SetSpotlight(true); + // (*myref)->SetSpotlight(true); + // (*myref)->Dump((*myref)->GetID()); + // + // + // } + + } else { + //cout<<"no ref ped found: " <<endl; + //getc(stdin); + } } -int QuickestPathRouter::GetCommonDestinationCount(AccessPoint* ap1, AccessPoint* ap2){ - const vector<AccessPoint*>& aps1 = ap1->GetConnectingAPs(); - const vector<AccessPoint*>& aps2 = ap2->GetConnectingAPs(); - - vector<AccessPoint*> common; - - for(unsigned int i=0;i<aps1.size();i++){ - AccessPoint* from_AP=aps1[i]; - if(from_AP->GetID()==ap2->GetID()) continue; - for(unsigned int j=0;j<aps2.size();j++){ - AccessPoint* to_AP=aps2[j]; - if(to_AP->GetID()==ap1->GetID()) continue; - if(from_AP->GetID()==to_AP->GetID()){ - //only add if the destination is shorter than mine - //if(ap2->GetDistanceTo(FINAL_DEST_OUT)<from_AP->GetDistanceTo(FINAL_DEST_OUT)) - //if(ap1->GetDistanceTo(FINAL_DEST_OUT)<from_AP->GetDistanceTo(FINAL_DEST_OUT)) - common.push_back(from_AP); - } - } - } - - std::sort(common.begin(), common.end()); - common.erase(std::unique(common.begin(), common.end()), common.end()); - - return common.size(); +int QuickestPathRouter::GetCommonDestinationCount(AccessPoint* ap1, AccessPoint* ap2) +{ + const vector<AccessPoint*>& aps1 = ap1->GetConnectingAPs(); + const vector<AccessPoint*>& aps2 = ap2->GetConnectingAPs(); + + vector<AccessPoint*> common; + + for(unsigned int i=0; i<aps1.size(); i++) { + AccessPoint* from_AP=aps1[i]; + if(from_AP->GetID()==ap2->GetID()) continue; + for(unsigned int j=0; j<aps2.size(); j++) { + AccessPoint* to_AP=aps2[j]; + if(to_AP->GetID()==ap1->GetID()) continue; + if(from_AP->GetID()==to_AP->GetID()) { + //only add if the destination is shorter than mine + //if(ap2->GetDistanceTo(FINAL_DEST_OUT)<from_AP->GetDistanceTo(FINAL_DEST_OUT)) + //if(ap1->GetDistanceTo(FINAL_DEST_OUT)<from_AP->GetDistanceTo(FINAL_DEST_OUT)) + common.push_back(from_AP); + } + } + } + + std::sort(common.begin(), common.end()); + common.erase(std::unique(common.begin(), common.end()), common.end()); + + return common.size(); } void QuickestPathRouter::GetQueueAtExit(Crossing* crossing, double minVel, - double radius, vector<Pedestrian*>& queue,int subroomToConsider){ - - SubRoom* sbr1 = crossing->GetSubRoom1(); - SubRoom* sbr2 = crossing->GetSubRoom2(); - //int exitID=crossing->GetID(); - int exitID=crossing->GetUniqueID(); - double radius2=radius*radius; - double minVel2=minVel*minVel; - - //if this is a hline - if(sbr1==sbr2){ - sbr2=NULL; - } - - if (sbr1 && (sbr1->GetSubRoomID()==subroomToConsider)){ - //double closestDistance=FLT_MAX; - const vector<Pedestrian*>& peds = sbr1->GetAllPedestrians(); - for (unsigned int p=0;p<peds.size();p++){ - Pedestrian* ped = peds[p]; - if(ped->GetExitIndex()==exitID){ - if(ped->GetV().NormSquare()<minVel2){ - double dist= (ped->GetPos()-crossing->GetCentre()).NormSquare(); - //cout<<"suspect found 1 @ "<< dist<< " { "<< closestDistance<<" }"<<endl; - if(dist<radius2){ - queue.push_back(ped); - } - } - } - } - } - - if (sbr2 && (sbr2->GetSubRoomID()==subroomToConsider)){ - //double closestDistance=FLT_MAX; - const vector<Pedestrian*>& peds = sbr2->GetAllPedestrians(); - for (unsigned int p=0;p<peds.size();p++){ - Pedestrian* ped = peds[p]; - if(ped->GetExitIndex()==exitID){ - if(ped->GetV().NormSquare()<minVel2){ - double dist= (ped->GetPos()-crossing->GetCentre()).NormSquare(); - //cout<<"distance: radius"<<dist<<":"<<radius<<endl; - //cout<<"suspect found 1 @ "<< dist<< " { "<< closestDistance<<" }"<<endl; - if(dist<radius2){ - queue.push_back(ped); - } - } - } - } - } - //cout<<"queue size:"<<queue.size()<<endl; - //cout<<"mean val:"<<minVel2<<endl; + double radius, vector<Pedestrian*>& queue,int subroomToConsider) +{ + + SubRoom* sbr1 = crossing->GetSubRoom1(); + SubRoom* sbr2 = crossing->GetSubRoom2(); + //int exitID=crossing->GetID(); + int exitID=crossing->GetUniqueID(); + double radius2=radius*radius; + double minVel2=minVel*minVel; + + //if this is a hline + if(sbr1==sbr2) { + sbr2=NULL; + } + + if (sbr1 && (sbr1->GetSubRoomID()==subroomToConsider)) { + //double closestDistance=FLT_MAX; + const vector<Pedestrian*>& peds = sbr1->GetAllPedestrians(); + for (unsigned int p=0; p<peds.size(); p++) { + Pedestrian* ped = peds[p]; + if(ped->GetExitIndex()==exitID) { + if(ped->GetV().NormSquare()<minVel2) { + double dist= (ped->GetPos()-crossing->GetCentre()).NormSquare(); + //cout<<"suspect found 1 @ "<< dist<< " { "<< closestDistance<<" }"<<endl; + if(dist<radius2) { + queue.push_back(ped); + } + } + } + } + } + + if (sbr2 && (sbr2->GetSubRoomID()==subroomToConsider)) { + //double closestDistance=FLT_MAX; + const vector<Pedestrian*>& peds = sbr2->GetAllPedestrians(); + for (unsigned int p=0; p<peds.size(); p++) { + Pedestrian* ped = peds[p]; + if(ped->GetExitIndex()==exitID) { + if(ped->GetV().NormSquare()<minVel2) { + double dist= (ped->GetPos()-crossing->GetCentre()).NormSquare(); + //cout<<"distance: radius"<<dist<<":"<<radius<<endl; + //cout<<"suspect found 1 @ "<< dist<< " { "<< closestDistance<<" }"<<endl; + if(dist<radius2) { + queue.push_back(ped); + } + } + } + } + } + //cout<<"queue size:"<<queue.size()<<endl; + //cout<<"mean val:"<<minVel2<<endl; } -bool QuickestPathRouter::IsDirectVisibilityBetween(Pedestrian* ped, Pedestrian* ref){ +bool QuickestPathRouter::IsDirectVisibilityBetween(Pedestrian* ped, Pedestrian* ref) +{ - int ignore_ped1=ped->GetID(); - int ignore_ped2=ref->GetID(); - Crossing* ignore_crossing=_building->GetTransOrCrossByUID(ref->GetExitIndex()); + int ignore_ped1=ped->GetID(); + int ignore_ped2=ref->GetID(); + Crossing* ignore_crossing=_building->GetTransOrCrossByUID(ref->GetExitIndex()); - int obstacles=GetObstaclesCountBetween(ped->GetPos(),ref->GetPos(),ignore_crossing,ignore_ped1,ignore_ped2); + int obstacles=GetObstaclesCountBetween(ped->GetPos(),ref->GetPos(),ignore_crossing,ignore_ped1,ignore_ped2); - if(obstacles>OBSTRUCTION) return false; - return true; + if(obstacles>OBSTRUCTION) return false; + return true; } -bool QuickestPathRouter::IsDirectVisibilityBetween(Pedestrian* myself, Crossing* crossing){ +bool QuickestPathRouter::IsDirectVisibilityBetween(Pedestrian* myself, Crossing* crossing) +{ - int ignore_ped1=myself->GetID(); - int ignore_ped2=-1;//there is no second ped to ignore + int ignore_ped1=myself->GetID(); + int ignore_ped2=-1;//there is no second ped to ignore - int obstacles=GetObstaclesCountBetween(myself->GetPos(),crossing->GetCentre(),crossing,ignore_ped1,ignore_ped2); + int obstacles=GetObstaclesCountBetween(myself->GetPos(),crossing->GetCentre(),crossing,ignore_ped1,ignore_ped2); - if(obstacles>OBSTRUCTION) return false; - return true; + if(obstacles>OBSTRUCTION) return false; + return true; } int QuickestPathRouter::GetObstaclesCountBetween(const Point& p1, const Point& p2, Crossing* crossing, - int ignore_ped1, int ignore_ped2){ + int ignore_ped1, int ignore_ped2) +{ - SubRoom* sbr1 = crossing->GetSubRoom1(); - SubRoom* sbr2 = crossing->GetSubRoom2(); - Line visibilityLine = Line(p1,p2); + SubRoom* sbr1 = crossing->GetSubRoom1(); + SubRoom* sbr2 = crossing->GetSubRoom2(); + Line visibilityLine = Line(p1,p2); - int exitID=crossing->GetID(); - int obstacles=0; + int exitID=crossing->GetID(); + int obstacles=0; - //if this is a hline - if(sbr1==sbr2){ - sbr2=NULL; - } + //if this is a hline + if(sbr1==sbr2) { + sbr2=NULL; + } - if (sbr1){ - const vector<Pedestrian*>& peds = sbr1->GetAllPedestrians(); - for (unsigned int p=0;p<peds.size();p++){ - Pedestrian* ped = peds[p]; + if (sbr1) { + const vector<Pedestrian*>& peds = sbr1->GetAllPedestrians(); + for (unsigned int p=0; p<peds.size(); p++) { + Pedestrian* ped = peds[p]; - //avoiding myself - if(ped->GetID()==ignore_ped1) continue; - if(ped->GetID()==ignore_ped2) continue; - // pedestrian going in that direction are not obstacles to me - if(ped->GetExitIndex()==exitID) continue; + //avoiding myself + if(ped->GetID()==ignore_ped1) continue; + if(ped->GetID()==ignore_ped2) continue; + // pedestrian going in that direction are not obstacles to me + if(ped->GetExitIndex()==exitID) continue; - if(visibilityLine.IntersectionWithCircle(ped->GetPos())){ - obstacles++; - if(obstacles>OBSTRUCTION) return obstacles; - } + if(visibilityLine.IntersectionWithCircle(ped->GetPos())) { + obstacles++; + if(obstacles>OBSTRUCTION) return obstacles; + } - } - } + } + } - if (sbr2){ - const vector<Pedestrian*>& peds = sbr2->GetAllPedestrians(); - for (unsigned int p=0;p<peds.size();p++){ - Pedestrian* ped = peds[p]; + if (sbr2) { + const vector<Pedestrian*>& peds = sbr2->GetAllPedestrians(); + for (unsigned int p=0; p<peds.size(); p++) { + Pedestrian* ped = peds[p]; - //avoiging myself - if(ped->GetID()==ignore_ped1) continue; - if(ped->GetID()==ignore_ped2) continue; - // pedestrian going in that direction are not obstacles to me - if(ped->GetExitIndex()==exitID) continue; + //avoiging myself + if(ped->GetID()==ignore_ped1) continue; + if(ped->GetID()==ignore_ped2) continue; + // pedestrian going in that direction are not obstacles to me + if(ped->GetExitIndex()==exitID) continue; - if(visibilityLine.IntersectionWithCircle(ped->GetPos())){ - obstacles++; - if(obstacles>OBSTRUCTION) return obstacles; - } + if(visibilityLine.IntersectionWithCircle(ped->GetPos())) { + obstacles++; + if(obstacles>OBSTRUCTION) return obstacles; + } - } - } + } + } - return obstacles; + return obstacles; } -int QuickestPathRouter::isCongested(Pedestrian* ped){ +int QuickestPathRouter::isCongested(Pedestrian* ped) +{ - //define as the ratio of people in front of me and behind me + //define as the ratio of people in front of me and behind me - Room* room=_building->GetRoom(ped->GetRoomID()); - SubRoom* sub=room->GetSubRoom(ped->GetSubRoomID()); - const vector<Pedestrian*>& allPeds=sub->GetAllPedestrians(); + Room* room=_building->GetRoom(ped->GetRoomID()); + SubRoom* sub=room->GetSubRoom(ped->GetSubRoomID()); + const vector<Pedestrian*>& allPeds=sub->GetAllPedestrians(); - //in the case there are only few people in the room - if(allPeds.size()<=OBSTRUCTION) return false; + //in the case there are only few people in the room + if(allPeds.size()<=OBSTRUCTION) return false; - double myDist=ped->GetDistanceToNextTarget(); - double inFrontofMe=0; - double behindMe=0; + double myDist=ped->GetDistanceToNextTarget(); + double inFrontofMe=0; + double behindMe=0; - for (unsigned int p=0;p<allPeds.size();p++){ - Pedestrian* ped2 = allPeds[p]; - //only consider pedestrians that are going in my direction - // caution this will not work with hlines - if(ped2->GetExitIndex()!=ped->GetExitIndex()) continue; - // skip myself - if(ped2->GetID()==ped->GetID()) continue; + for (unsigned int p=0; p<allPeds.size(); p++) { + Pedestrian* ped2 = allPeds[p]; + //only consider pedestrians that are going in my direction + // caution this will not work with hlines + if(ped2->GetExitIndex()!=ped->GetExitIndex()) continue; + // skip myself + if(ped2->GetID()==ped->GetID()) continue; - if(myDist>ped2->GetDistanceToNextTarget()){ - inFrontofMe++; - } else { - behindMe++; - } - } + if(myDist>ped2->GetDistanceToNextTarget()) { + inFrontofMe++; + } else { + behindMe++; + } + } - double ratio=inFrontofMe/(inFrontofMe+behindMe); + double ratio=inFrontofMe/(inFrontofMe+behindMe); - // if(ped->GetID()==255) cout<<"ratio:"<<ratio<<endl; - // if((ped->GetID()==255) && (ratio>0.8)){ - // cout<<"ratio:"<<ratio<<endl; - // ped->Dump(255); - // exit(0); - // } + // if(ped->GetID()==255) cout<<"ratio:"<<ratio<<endl; + // if((ped->GetID()==255) && (ratio>0.8)){ + // cout<<"ratio:"<<ratio<<endl; + // ped->Dump(255); + // exit(0); + // } - if(ratio>0.8) return true; + if(ratio>0.8) return true; - return false; + return false; - //if(ped->GetID()==88) - //cout<<"ratio:"<<ratio<<endl; - //return true; - /* - //collect the pedestrians within 1 metre radius - vector<Pedestrian*> neighbourhood; - double range=1.0;//1m + //if(ped->GetID()==88) + //cout<<"ratio:"<<ratio<<endl; + //return true; + /* + //collect the pedestrians within 1 metre radius + vector<Pedestrian*> neighbourhood; + double range=1.0;//1m - _building->GetGrid()->GetNeighbourhood(ped,neighbourhood); + _building->GetGrid()->GetNeighbourhood(ped,neighbourhood); - std::vector<int> conflictings; - std::vector<int>::iterator per; + std::vector<int> conflictings; + std::vector<int>::iterator per; - //int congested=1; - int pedCrossing=0; + //int congested=1; + int pedCrossing=0; - //Debug::Messages("congested ( %hd ): [ ",myID); + //Debug::Messages("congested ( %hd ): [ ",myID); - Point start=ped->GetPos(); - //looping on a circle - for(double phi=0.0; phi<2*M_PI; phi+=0.1){ + Point start=ped->GetPos(); + //looping on a circle + for(double phi=0.0; phi<2*M_PI; phi+=0.1){ - Point end= start+Point(range*cos(phi), range*sin(phi));//translation + Point end= start+Point(range*cos(phi), range*sin(phi));//translation - Line line= Line(start, end); + Line line= Line(start, end); - for(unsigned int p=0;p<neighbourhood.size();p++){ - Pedestrian* ref = neighbourhood[p]; + for(unsigned int p=0;p<neighbourhood.size();p++){ + Pedestrian* ref = neighbourhood[p]; - //skipping those in other rooms - if(ped->GetUniqueRoomID()!=ref->GetUniqueRoomID()) continue; + //skipping those in other rooms + if(ped->GetUniqueRoomID()!=ref->GetUniqueRoomID()) continue; - if((ped->GetPos()-ref->GetPos()).NormSquare()>1.0) continue; - // do not add a pedestrian twice - vector<int>::iterator per = find(conflictings.begin(), conflictings.end(), ref->GetID()); - if (per != conflictings.end()) continue; + if((ped->GetPos()-ref->GetPos()).NormSquare()>1.0) continue; + // do not add a pedestrian twice + vector<int>::iterator per = find(conflictings.begin(), conflictings.end(), ref->GetID()); + if (per != conflictings.end()) continue; - if(line.IntersectionWithCircle(ref->GetPos())==false) continue; + if(line.IntersectionWithCircle(ref->GetPos())==false) continue; - const Point& pos1=ref->GetPos(); - Point pos2= start-pos1; - Point vel1=ped->GetV(); + const Point& pos1=ref->GetPos(); + Point pos2= start-pos1; + Point vel1=ped->GetV(); - // only those behind me - if(pos2.ScalarP(vel1)) pedCrossing++; + // only those behind me + if(pos2.ScalarP(vel1)) pedCrossing++; - conflictings.push_back(ref->GetID()); + conflictings.push_back(ref->GetID()); - } + } - } + } - if(pedCrossing<OBSTRUCTION) return false; + if(pedCrossing<OBSTRUCTION) return false; - return true; - */ + return true; + */ } -double QuickestPathRouter::GetEstimatedTravelTimeVia(Pedestrian* ped, int exitid){ +double QuickestPathRouter::GetEstimatedTravelTimeVia(Pedestrian* ped, int exitid) +{ - //select a reference pedestrian - Pedestrian* myref=NULL; - int flag=FREE_EXIT; //assume free exit - SelectReferencePedestrian(ped,&myref,J_QUEUE_VEL_THRESHOLD_JAM,exitid,&flag); + //select a reference pedestrian + Pedestrian* myref=NULL; + int flag=FREE_EXIT; //assume free exit + SelectReferencePedestrian(ped,&myref,J_QUEUE_VEL_THRESHOLD_JAM,exitid,&flag); - AccessPoint* ap=_accessPoints[exitid]; + AccessPoint* ap=_accessPoints[exitid]; - // compute the time - double time=FLT_MAX; + // compute the time + double time=FLT_MAX; - // case of free exit - if((myref==NULL)&& (flag==FREE_EXIT)){ - double t1 = (ped->GetPos()- ap->GetCentre()).Norm()/ped->GetV0Norm(); - // time to reach the AP - //double t1 = (ped->GetPos()- ap->GetCentre()).Norm()/ped->GetV().Norm(); + // case of free exit + if((myref==NULL)&& (flag==FREE_EXIT)) { + double t1 = (ped->GetPos()- ap->GetCentre()).Norm()/ped->GetV0Norm(); + // time to reach the AP + //double t1 = (ped->GetPos()- ap->GetCentre()).Norm()/ped->GetV().Norm(); - //guess time from the Ap to the outside - double t2 = (ap->GetDistanceTo(ped->GetFinalDestination()))/ped->GetV0Norm(); + //guess time from the Ap to the outside + double t2 = (ap->GetDistanceTo(ped->GetFinalDestination()))/ped->GetV0Norm(); - time=t1+t2; - } + time=t1+t2; + } - // case of unreachable exit - if((myref==NULL)&& (flag==UNREACHEABLE_EXIT)){ - time= FLT_MAX; - } + // case of unreachable exit + if((myref==NULL)&& (flag==UNREACHEABLE_EXIT)) { + time= FLT_MAX; + } - // case of ref ped - if((myref!=NULL) && (flag==REF_PED_FOUND)){ + // case of ref ped + if((myref!=NULL) && (flag==REF_PED_FOUND)) { - //time to reach the reference - double t1= (ped->GetPos()- myref->GetPos()).Norm()/ped->GetV().Norm(); - //double t1= (ped->GetPos()- myref->GetPos()).Norm()/ped->GetV0Norm(); + //time to reach the reference + double t1= (ped->GetPos()- myref->GetPos()).Norm()/ped->GetV().Norm(); + //double t1= (ped->GetPos()- myref->GetPos()).Norm()/ped->GetV0Norm(); - if(myref->GetV().Norm()==0.0){ - Log->Write("ERROR:\t the reference pedestrian velocity is zero"); exit(0); - } - //time for the reference to get out - double t2=(myref->GetPos() - ap->GetCentre()).Norm()/myref->GetV().Norm(); + if(myref->GetV().Norm()==0.0) { + Log->Write("ERROR:\t the reference pedestrian velocity is zero"); + exit(0); + } + //time for the reference to get out + double t2=(myref->GetPos() - ap->GetCentre()).Norm()/myref->GetV().Norm(); - //guess time from the Ap to the outside - //double t3 = (ap->GetDistanceTo(ped->GetFinalDestination()))/ped->GetV().Norm(); - // we assume the desired velocity, because we cannot see anything - double t3 = (ap->GetDistanceTo(ped->GetFinalDestination()))/ped->GetV0Norm(); + //guess time from the Ap to the outside + //double t3 = (ap->GetDistanceTo(ped->GetFinalDestination()))/ped->GetV().Norm(); + // we assume the desired velocity, because we cannot see anything + double t3 = (ap->GetDistanceTo(ped->GetFinalDestination()))/ped->GetV0Norm(); - time=t1+t2+t3; - } + time=t1+t2+t3; + } - if((myref==NULL) && (flag==REF_PED_FOUND)){ - cout<<" Fatal Error in Quickest Path Router"<<endl; - cout<<" reference pedestrians is NULL"<<endl; - exit(EXIT_FAILURE); + if((myref==NULL) && (flag==REF_PED_FOUND)) { + cout<<" Fatal Error in Quickest Path Router"<<endl; + cout<<" reference pedestrians is NULL"<<endl; + exit(EXIT_FAILURE); - } + } - return time; + return time; } -void QuickestPathRouter::Redirect(Pedestrian* ped){ - - int preferredExit=ped->GetExitIndex(); - - double preferredExitTime=FLT_MAX; - int quickest=-1; - double minTime=FLT_MAX; - - //only redirect to other final exits in the actual room. - // if there is no final exit in the sight range, - // then no redirection is possible - - // collect the possible alternatives - Room* room=_building->GetRoom(ped->GetRoomID()); - SubRoom* sub=room->GetSubRoom(ped->GetSubRoomID()); - - //const vector<int>& goals=room->GetAllTransitionsIDs(); - //filter to keep only the emergencies exits. - - vector <AccessPoint*> relevantAPs; - GetRelevantRoutesTofinalDestination(ped,relevantAPs); - - for(unsigned int g=0;g<relevantAPs.size();g++){ - AccessPoint* ap=relevantAPs[g]; - int exitid=ap->GetID(); - // } - // - // for(unsigned int g=0;g<goals.size();g++){ - // int exitid=goals[g]; - // AccessPoint* ap=_accessPoints[exitid]; - - //only final are accounted - //if(ap->GetFinalExitToOutside()==false) continue; - - //check if I can reach that exit, there should exits a direct line - // segment connecting the two APs/goals - const Point& p1 = ap->GetCentre(); - const Point& p2 = ped->GetPos(); - Line segment = Line(p1,p2); - - bool isVisible=true; - //first walls - const vector<Wall>& walls= sub->GetAllWalls(); - - for(unsigned int b=0;b<walls.size();b++){ - if(segment.IntersectionWith(walls[b])==true) { - isVisible=false; - break; - } - } - if(isVisible==false) continue; - - double time=GetEstimatedTravelTimeVia(ped, exitid); - - if(time<minTime){ - minTime=time; - quickest=exitid; - } - - //printf(" ped [%d] checking [%d] ---> [%f]\n",ped->GetPedIndex(),exitid,time); - //also save the time for the default destinations for later comparison - if (exitid==preferredExit){ - preferredExitTime=time; - } - - } - //compare it with my preferred/current (shortest nearest) - if(quickest!=preferredExit){ - double cba = CBA(gain(preferredExitTime),gain(minTime)); - //cout<<"cba:" <<cba<<endl; - if (cba>CBA_THRESHOLD){ - ped->SetExitIndex(quickest); - ped->SetExitLine(_accessPoints[quickest]->GetNavLine()); - //ped->SetSpotlight(false); - } - } +void QuickestPathRouter::Redirect(Pedestrian* ped) +{ + + int preferredExit=ped->GetExitIndex(); + + double preferredExitTime=FLT_MAX; + int quickest=-1; + double minTime=FLT_MAX; + + //only redirect to other final exits in the actual room. + // if there is no final exit in the sight range, + // then no redirection is possible + + // collect the possible alternatives + Room* room=_building->GetRoom(ped->GetRoomID()); + SubRoom* sub=room->GetSubRoom(ped->GetSubRoomID()); + + //const vector<int>& goals=room->GetAllTransitionsIDs(); + //filter to keep only the emergencies exits. + + vector <AccessPoint*> relevantAPs; + GetRelevantRoutesTofinalDestination(ped,relevantAPs); + + for(unsigned int g=0; g<relevantAPs.size(); g++) { + AccessPoint* ap=relevantAPs[g]; + int exitid=ap->GetID(); + // } + // + // for(unsigned int g=0;g<goals.size();g++){ + // int exitid=goals[g]; + // AccessPoint* ap=_accessPoints[exitid]; + + //only final are accounted + //if(ap->GetFinalExitToOutside()==false) continue; + + //check if I can reach that exit, there should exits a direct line + // segment connecting the two APs/goals + const Point& p1 = ap->GetCentre(); + const Point& p2 = ped->GetPos(); + Line segment = Line(p1,p2); + + bool isVisible=true; + //first walls + const vector<Wall>& walls= sub->GetAllWalls(); + + for(unsigned int b=0; b<walls.size(); b++) { + if(segment.IntersectionWith(walls[b])==true) { + isVisible=false; + break; + } + } + if(isVisible==false) continue; + + double time=GetEstimatedTravelTimeVia(ped, exitid); + + if(time<minTime) { + minTime=time; + quickest=exitid; + } + + //printf(" ped [%d] checking [%d] ---> [%f]\n",ped->GetPedIndex(),exitid,time); + //also save the time for the default destinations for later comparison + if (exitid==preferredExit) { + preferredExitTime=time; + } + + } + //compare it with my preferred/current (shortest nearest) + if(quickest!=preferredExit) { + double cba = CBA(gain(preferredExitTime),gain(minTime)); + //cout<<"cba:" <<cba<<endl; + if (cba>CBA_THRESHOLD) { + ped->SetExitIndex(quickest); + ped->SetExitLine(_accessPoints[quickest]->GetNavLine()); + //ped->SetSpotlight(false); + } + } } diff --git a/routing/QuickestPathRouter.h b/routing/QuickestPathRouter.h index b486799cd5d10a2aa2e4c73f15457b88a08abf66..585c2fcf278d27e5a3fe6ca3a44889d9a2b79847 100644 --- a/routing/QuickestPathRouter.h +++ b/routing/QuickestPathRouter.h @@ -48,189 +48,189 @@ extern OutputHandler* Log; class QuickestPathRouter: public GlobalRouter { - public: - QuickestPathRouter(); - virtual ~QuickestPathRouter(); - - virtual int FindExit(Pedestrian* ped); - virtual void Init(Building* building); - - private: - - /** - * @return the right path for the extra information - */ - virtual std::string GetRoutingInfoFile() const; - - /** - * find the next suitable destination for the pedestrian - * @param ped - * @return the index of the destination - */ - int FindNextExit(Pedestrian* ped); - - /** - * compute the best route for the pedestrian - * - * @param ped the pedestrian - * @param nearestAP the nearest decision point - * @return the best route found - */ - - int GetQuickestRoute(Pedestrian*ped, AccessPoint* nearestAP); - - /** - * compute the cost benefit analysis obtained by changing from value g1 to value g2 - * @param g1, the reference value - * @param g2, the value to compare to - * @return the gain - */ - double CBA (double ref_g1, double comp_g2); - - - /** - * compute the gain related to this travelling time - */ - double gain(double time); - - /** - * compute the similarity between two values, - * normaly distances - * @param x1 - * @param x2 - * @return - */ - double similarity (double x1, double x2); - - /** - * return the turning angle penalty - * - * @param alpha [0..pi], the considered angle if change is undertaken - * @return, the value of the penalty - */ - double TAP (double alpha); - - - /** - * \brief determines if a pedestrian is within (in a centre) of a jam. - * - * This function calculates the degree of congestion of a pedestrian. - * -1 is returned if the ped has no choice than to follow his actual goal, - * otherwise a value [0 1] is returned. 0 means free and 1 mean fully stuck - * in jam. - * - * @param pedIndex, the index of the pedestrian - * @return the degree of congestion - */ - int isCongested(Pedestrian* ped); - - - /** - * redirect a pedestrian based on the actual traffic conditions: - * i.e if IsCongested returned false - * @see isCongested - * - * @param ped the pedestrian to be redirected - */ - virtual void Redirect(Pedestrian* ped); - - - /// select the references pedestrians for this one - void selectReferencePeds(int pedIndex, int myCurrentDoor=-1); - - /** - * redirect a pedestrian based on the actual jamming conditions - * - * @param pedindex - * @param actualexit - * @return - */ - int redirect(int pedindex,int actualexit=-1); - - - double GetJamSizeAtExit(int exitID); - - /** - * select a reference pedestrian for an exit. - * In the case NULL is returned, check the flag to see why. - * Reasons are: - * flag=0: a proper reference was found - * flag=1: the exit is free, no reference - * flag=2: I can't see the exit, nor references, too crowded, too many crossing pedes - */ - void SelectReferencePedestrian(Pedestrian* me, Pedestrian** myref, double JamThreshold, int exitID, int* flag); - - /** - * extend the graph by connecting alternative routes. - */ - void ExpandGraph(); - - /** - * reduce the graph, making it to a directed graph to the outside - */ - void ReduceGraph(); - - - /** - * check the nodes that are double self linked and remove the connection with the highest radian - */ - void CheckAndClearDoubleLinkedNodes(); - - /** - * return the number of common nodes the two aps are connected with or pointing to. - */ - int GetCommonDestinationCount(AccessPoint* ap1, AccessPoint* ap2); - - - - - /** - * return the queue at the specified exit within the specified radius - * if subroomToConsider == -1 then the two side of the crossing will be considered - * - */ - void GetQueueAtExit(Crossing* crossing, double minVel, - double radius, std::vector<Pedestrian*>& queue, int subroomToConsider=-1); - - - /** - * Check if two pedestrian can see each other - * - * @param ped, the pedestrian being investigated - * @param ref, the reference pedestrian - * @return true if both can see each other - */ - bool IsDirectVisibilityBetween(Pedestrian* ped, Pedestrian* ref); - - /** - * Check if a pedestrian can see a crossing - * - * @param ped, the pedestrian being investigated - * @param ref, the crossing/exit - * @return true if there is a direct visibility - */ - bool IsDirectVisibilityBetween(Pedestrian* ped, Crossing* ref); - - /** - * returns the number of obstacles between the points p1 and p2 with respect - * to the crossing crossing. The pedestrians ped1 and ped2 are not accounted in the obstacles. - * - * @param p1 the start point - * @param p2 the end point - * @param crossing - * @param ignore_ped1 - * @param ignore_ped2 - * @return the number of obstacles - */ - int GetObstaclesCountBetween(const Point& p1, const Point& p2, Crossing* crossing, int ignore_ped1, int ignore_ped2); - - /** - * - * @param ped the pedestrian doing the estimation - * @param exitID the exit ID - * @return the estimated travel time via the given exit - */ - double GetEstimatedTravelTimeVia(Pedestrian* ped, int exitID); +public: + QuickestPathRouter(); + virtual ~QuickestPathRouter(); + + virtual int FindExit(Pedestrian* ped); + virtual void Init(Building* building); + +private: + + /** + * @return the right path for the extra information + */ + virtual std::string GetRoutingInfoFile() const; + + /** + * find the next suitable destination for the pedestrian + * @param ped + * @return the index of the destination + */ + int FindNextExit(Pedestrian* ped); + + /** + * compute the best route for the pedestrian + * + * @param ped the pedestrian + * @param nearestAP the nearest decision point + * @return the best route found + */ + + int GetQuickestRoute(Pedestrian*ped, AccessPoint* nearestAP); + + /** + * compute the cost benefit analysis obtained by changing from value g1 to value g2 + * @param g1, the reference value + * @param g2, the value to compare to + * @return the gain + */ + double CBA (double ref_g1, double comp_g2); + + + /** + * compute the gain related to this travelling time + */ + double gain(double time); + + /** + * compute the similarity between two values, + * normaly distances + * @param x1 + * @param x2 + * @return + */ + double similarity (double x1, double x2); + + /** + * return the turning angle penalty + * + * @param alpha [0..pi], the considered angle if change is undertaken + * @return, the value of the penalty + */ + double TAP (double alpha); + + + /** + * \brief determines if a pedestrian is within (in a centre) of a jam. + * + * This function calculates the degree of congestion of a pedestrian. + * -1 is returned if the ped has no choice than to follow his actual goal, + * otherwise a value [0 1] is returned. 0 means free and 1 mean fully stuck + * in jam. + * + * @param pedIndex, the index of the pedestrian + * @return the degree of congestion + */ + int isCongested(Pedestrian* ped); + + + /** + * redirect a pedestrian based on the actual traffic conditions: + * i.e if IsCongested returned false + * @see isCongested + * + * @param ped the pedestrian to be redirected + */ + virtual void Redirect(Pedestrian* ped); + + + /// select the references pedestrians for this one + void selectReferencePeds(int pedIndex, int myCurrentDoor=-1); + + /** + * redirect a pedestrian based on the actual jamming conditions + * + * @param pedindex + * @param actualexit + * @return + */ + int redirect(int pedindex,int actualexit=-1); + + + double GetJamSizeAtExit(int exitID); + + /** + * select a reference pedestrian for an exit. + * In the case NULL is returned, check the flag to see why. + * Reasons are: + * flag=0: a proper reference was found + * flag=1: the exit is free, no reference + * flag=2: I can't see the exit, nor references, too crowded, too many crossing pedes + */ + void SelectReferencePedestrian(Pedestrian* me, Pedestrian** myref, double JamThreshold, int exitID, int* flag); + + /** + * extend the graph by connecting alternative routes. + */ + void ExpandGraph(); + + /** + * reduce the graph, making it to a directed graph to the outside + */ + void ReduceGraph(); + + + /** + * check the nodes that are double self linked and remove the connection with the highest radian + */ + void CheckAndClearDoubleLinkedNodes(); + + /** + * return the number of common nodes the two aps are connected with or pointing to. + */ + int GetCommonDestinationCount(AccessPoint* ap1, AccessPoint* ap2); + + + + + /** + * return the queue at the specified exit within the specified radius + * if subroomToConsider == -1 then the two side of the crossing will be considered + * + */ + void GetQueueAtExit(Crossing* crossing, double minVel, + double radius, std::vector<Pedestrian*>& queue, int subroomToConsider=-1); + + + /** + * Check if two pedestrian can see each other + * + * @param ped, the pedestrian being investigated + * @param ref, the reference pedestrian + * @return true if both can see each other + */ + bool IsDirectVisibilityBetween(Pedestrian* ped, Pedestrian* ref); + + /** + * Check if a pedestrian can see a crossing + * + * @param ped, the pedestrian being investigated + * @param ref, the crossing/exit + * @return true if there is a direct visibility + */ + bool IsDirectVisibilityBetween(Pedestrian* ped, Crossing* ref); + + /** + * returns the number of obstacles between the points p1 and p2 with respect + * to the crossing crossing. The pedestrians ped1 and ped2 are not accounted in the obstacles. + * + * @param p1 the start point + * @param p2 the end point + * @param crossing + * @param ignore_ped1 + * @param ignore_ped2 + * @return the number of obstacles + */ + int GetObstaclesCountBetween(const Point& p1, const Point& p2, Crossing* crossing, int ignore_ped1, int ignore_ped2); + + /** + * + * @param ped the pedestrian doing the estimation + * @param exitID the exit ID + * @return the estimated travel time via the given exit + */ + double GetEstimatedTravelTimeVia(Pedestrian* ped, int exitID); }; #endif /* QUICKESTPATHROUTER_H_ */ diff --git a/routing/Router.cpp b/routing/Router.cpp index def30c8cbd2c4ccbba0037dab233a29e19bf4821..a61854b0a5e87aa135ed379be0a37e6a551c4fca 100644 --- a/routing/Router.cpp +++ b/routing/Router.cpp @@ -32,58 +32,69 @@ using namespace std; -Router::Router() { - _trips = vector<vector<int> >(); - _finalDestinations = vector<int>(); - _id=-1; - _strategy=ROUTING_UNDEFINED; +Router::Router() +{ + _trips = vector<vector<int> >(); + _finalDestinations = vector<int>(); + _id=-1; + _strategy=ROUTING_UNDEFINED; } -Router::~Router() { +Router::~Router() +{ } -const vector<int> Router::GetTrip(int index) const { - if ((index >= 0) && (index < (int) _trips.size())) - return _trips[index]; - else { - char tmp[CLENGTH]; - sprintf(tmp, "ERROR: \tWrong 'index' [%d] > [%d] in Routing::GetTrip()", - index, _trips.size()); - Log->Write(tmp); - exit(EXIT_FAILURE); - } +const vector<int> Router::GetTrip(int index) const +{ + if ((index >= 0) && (index < (int) _trips.size())) + return _trips[index]; + else { + char tmp[CLENGTH]; + sprintf(tmp, "ERROR: \tWrong 'index' [%d] > [%d] in Routing::GetTrip()", + index, _trips.size()); + Log->Write(tmp); + exit(EXIT_FAILURE); + } } -void Router::AddTrip(vector<int> trip) { - _trips.push_back(trip); +void Router::AddTrip(vector<int> trip) +{ + _trips.push_back(trip); } -void Router::AddFinalDestinationID(int id) { - _finalDestinations.push_back(id); +void Router::AddFinalDestinationID(int id) +{ + _finalDestinations.push_back(id); } -const vector<int> Router::GetFinalDestinations() const { - return _finalDestinations; +const vector<int> Router::GetFinalDestinations() const +{ + return _finalDestinations; } -void Router::SetID(int id) { - _id=id; +void Router::SetID(int id) +{ + _id=id; } -int Router::GetID() const { - return _id; +int Router::GetID() const +{ + return _id; } -void Router::SetStrategy(RoutingStrategy strategy) { - _strategy=strategy; +void Router::SetStrategy(RoutingStrategy strategy) +{ + _strategy=strategy; } -RoutingStrategy Router::GetStrategy() const { - return _strategy; +RoutingStrategy Router::GetStrategy() const +{ + return _strategy; } -void Router::WriteToErrorLog() const { - //TODO +void Router::WriteToErrorLog() const +{ + //TODO // for (map<int, Crossing*>::const_iterator iter = pCrossings.begin(); // iter != pCrossings.end(); ++iter) { // iter->second->WriteToErrorLog(); diff --git a/routing/Router.h b/routing/Router.h index 9d94ec4f0ed393f685787b3cc9e89f48c143800a..dfb42fe0326c9e21f3f5d56338008417ca2f751a 100644 --- a/routing/Router.h +++ b/routing/Router.h @@ -38,90 +38,90 @@ class Pedestrian; class Router { - private: - /// routing strategy as defined in the Macros.h file - RoutingStrategy _strategy; - - /// the id as present in the persons.xml file - int _id; - - protected: - - /// Contain the ids of the intermediate destinations - std::vector<std::vector<int> >_trips; - - /// All final destinations of the pedestrians - std::vector<int> _finalDestinations; - - public: - Router(); - - virtual ~Router(); - - /** - * Add a new trip to this router - * @param trip A vector containing the IDs of the intermediate destination - */ - void AddTrip(std::vector<int> trip); - - /** - * Add a new final destination to this router - * @param id of an intermediate destination as presented in the geometry/routing files - */ - void AddFinalDestinationID(int id); - - - /** - * TODO: investigate Trip for compatibility with ID starting with 0 or 1. - * @return a vector containing the IDs of the intermediate destinations - */ - const std::vector<int> GetTrip(int id) const; - - /** - * @return all final destinations - */ - const std::vector<int> GetFinalDestinations() const; - - /** - * Set the id of the router as defined in the person file - */ - void SetID(int id); - - /** - * @return the id of the router as defined in the person file - */ - int GetID() const; - - /** - * The strategy is automatically set based on the description in the - * person file. - */ - void SetStrategy(RoutingStrategy strategy); - - /** - * The strategy is automatically set based on the description in the - * person file. - */ - RoutingStrategy GetStrategy() const; - - /** - * Debug output for this class - */ - void WriteToErrorLog() const; - - /** - * Find the next suitable target for Pedestrian p - * @param p the Pedestrian - * @return -1 in the case no destination could be found - */ - virtual int FindExit(Pedestrian* p) = 0; - - /** - * Each implementation of this virtual class has the possibility to initialize - * its Routing engine using the supplied building object. - * @param b the building object - */ - virtual void Init(Building* b) = 0; +private: + /// routing strategy as defined in the Macros.h file + RoutingStrategy _strategy; + + /// the id as present in the persons.xml file + int _id; + +protected: + + /// Contain the ids of the intermediate destinations + std::vector<std::vector<int> >_trips; + + /// All final destinations of the pedestrians + std::vector<int> _finalDestinations; + +public: + Router(); + + virtual ~Router(); + + /** + * Add a new trip to this router + * @param trip A vector containing the IDs of the intermediate destination + */ + void AddTrip(std::vector<int> trip); + + /** + * Add a new final destination to this router + * @param id of an intermediate destination as presented in the geometry/routing files + */ + void AddFinalDestinationID(int id); + + + /** + * TODO: investigate Trip for compatibility with ID starting with 0 or 1. + * @return a vector containing the IDs of the intermediate destinations + */ + const std::vector<int> GetTrip(int id) const; + + /** + * @return all final destinations + */ + const std::vector<int> GetFinalDestinations() const; + + /** + * Set the id of the router as defined in the person file + */ + void SetID(int id); + + /** + * @return the id of the router as defined in the person file + */ + int GetID() const; + + /** + * The strategy is automatically set based on the description in the + * person file. + */ + void SetStrategy(RoutingStrategy strategy); + + /** + * The strategy is automatically set based on the description in the + * person file. + */ + RoutingStrategy GetStrategy() const; + + /** + * Debug output for this class + */ + void WriteToErrorLog() const; + + /** + * Find the next suitable target for Pedestrian p + * @param p the Pedestrian + * @return -1 in the case no destination could be found + */ + virtual int FindExit(Pedestrian* p) = 0; + + /** + * Each implementation of this virtual class has the possibility to initialize + * its Routing engine using the supplied building object. + * @param b the building object + */ + virtual void Init(Building* b) = 0; }; diff --git a/routing/RoutingEngine.cpp b/routing/RoutingEngine.cpp index bb765eb2efd47a2bf2380f47a4aec644c26c758e..dc77bcd2e5b4853c6a1c906958d103719afbde07 100644 --- a/routing/RoutingEngine.cpp +++ b/routing/RoutingEngine.cpp @@ -11,74 +11,84 @@ using namespace std; -RoutingEngine::RoutingEngine() { +RoutingEngine::RoutingEngine() +{ } -RoutingEngine::~RoutingEngine() { - for(unsigned int r=0;r<_routersCollection.size();r++){ - delete _routersCollection[r]; - } - _routersCollection.clear(); +RoutingEngine::~RoutingEngine() +{ + for(unsigned int r=0; r<_routersCollection.size(); r++) { + delete _routersCollection[r]; + } + _routersCollection.clear(); } -void RoutingEngine::AddFinalDestinationID(int id) { - for(unsigned int r=0;r<_routersCollection.size();r++){ - _routersCollection[r]->AddFinalDestinationID(id); - } +void RoutingEngine::AddFinalDestinationID(int id) +{ + for(unsigned int r=0; r<_routersCollection.size(); r++) { + _routersCollection[r]->AddFinalDestinationID(id); + } } -void RoutingEngine::FindRoute(Pedestrian* ped) { - ped->FindRoute(); +void RoutingEngine::FindRoute(Pedestrian* ped) +{ + ped->FindRoute(); } -void RoutingEngine::AddRouter(Router* router) { - for(unsigned int r=0;r<_routersCollection.size();r++){ - if(_routersCollection[r]->GetStrategy()==router->GetStrategy()){ - Log->Write("ERROR: \tDuplicate router found with 'id' [%d].",router->GetID()); - Log->Write("ERROR: \tDouble check your configuration files"); - exit(EXIT_FAILURE); - } - } - _routersCollection.push_back(router); +void RoutingEngine::AddRouter(Router* router) +{ + for(unsigned int r=0; r<_routersCollection.size(); r++) { + if(_routersCollection[r]->GetStrategy()==router->GetStrategy()) { + Log->Write("ERROR: \tDuplicate router found with 'id' [%d].",router->GetID()); + Log->Write("ERROR: \tDouble check your configuration files"); + exit(EXIT_FAILURE); + } + } + _routersCollection.push_back(router); } -const vector<string> RoutingEngine::GetTrip(int index) const { - if ((index >= 0) && (index < (int) _tripsCollection.size())) - return _tripsCollection[index]; - else { - char tmp[CLENGTH]; - sprintf(tmp, "ERROR: \tWrong 'index' [%d] > [%d] in Routing::GetTrip()", - index, _tripsCollection.size()); - Log->Write(tmp); - exit(EXIT_FAILURE); - } +const vector<string> RoutingEngine::GetTrip(int index) const +{ + if ((index >= 0) && (index < (int) _tripsCollection.size())) + return _tripsCollection[index]; + else { + char tmp[CLENGTH]; + sprintf(tmp, "ERROR: \tWrong 'index' [%d] > [%d] in Routing::GetTrip()", + index, _tripsCollection.size()); + Log->Write(tmp); + exit(EXIT_FAILURE); + } } -Router* RoutingEngine::GetRouter(RoutingStrategy strategy) const { - for(unsigned int r=0;r<_routersCollection.size();r++){ - if(_routersCollection[r]->GetStrategy()==strategy) - return _routersCollection[r]; - } - //Log->Write("ERROR: \t Could not Find any router with ID: [%d].",strategy); - //exit(EXIT_FAILURE); - return (Router*) NULL; +Router* RoutingEngine::GetRouter(RoutingStrategy strategy) const +{ + for(unsigned int r=0; r<_routersCollection.size(); r++) { + if(_routersCollection[r]->GetStrategy()==strategy) + return _routersCollection[r]; + } + //Log->Write("ERROR: \t Could not Find any router with ID: [%d].",strategy); + //exit(EXIT_FAILURE); + return (Router*) NULL; } -Router* RoutingEngine::GetRouter(int id) const { - for(unsigned int r=0;r<_routersCollection.size();r++){ - if(_routersCollection[r]->GetID()==id) - return _routersCollection[r]; - } - return (Router*) NULL; +Router* RoutingEngine::GetRouter(int id) const +{ + for(unsigned int r=0; r<_routersCollection.size(); r++) { + if(_routersCollection[r]->GetID()==id) + return _routersCollection[r]; + } + return (Router*) NULL; } -void RoutingEngine::AddTrip(vector<string> trip) { - _tripsCollection.push_back(trip); +void RoutingEngine::AddTrip(vector<string> trip) +{ + _tripsCollection.push_back(trip); } -void RoutingEngine::Init(Building* building) { - for(unsigned int r=0;r<_routersCollection.size();r++){ - _routersCollection[r]->Init(building); - } +void RoutingEngine::Init(Building* building) +{ + for(unsigned int r=0; r<_routersCollection.size(); r++) { + _routersCollection[r]->Init(building); + } } diff --git a/routing/RoutingEngine.h b/routing/RoutingEngine.h index 92cc9adfddc9f11db5de48721e083da6813af842..c21c71e01a39d84aaeb30ac1148e23a1392e60ee 100644 --- a/routing/RoutingEngine.h +++ b/routing/RoutingEngine.h @@ -19,72 +19,72 @@ class Pedestrian; class RoutingEngine { - public: - /** - * Constructor - */ - RoutingEngine(); - - /** - * Destructor - */ - virtual ~RoutingEngine(); - - /** - * Add a final destination in the system. - * The destinations are segments (@see Transitions @see Crossings) - * @param id - */ - void AddFinalDestinationID(int id); - - /** - * Add a new trip to the system. Individual pedestrian can be assigned a particular trip. - * @param trip - */ - void AddTrip(std::vector<std::string> trip); - - /** - * Return a trip/route with the particular id - * FIXME referenz? - * @param id - * @return - */ - const std::vector<std::string> GetTrip(int id) const; - - /** - * Find the next destination using the appropriate router from - * the collection for the pedestrian ped. - */ - void FindRoute(Pedestrian* ped); - - - /** - * Add a new router to the routing system - * - */ - void AddRouter(Router* router); - - /** - * Return the router with the specified strategy - */ - Router* GetRouter(RoutingStrategy strategy) const; - - /** - * Return the router with the specified id - */ - Router* GetRouter(int id) const; - - /** - * Initialize all routers with the current building object - * @param building - */ - void Init(Building* building); - - private: - /// collections of all routers used - std::vector<Router*> _routersCollection; - /// collection of all trips/routes - std::vector<std::vector<std::string> >_tripsCollection; +public: + /** + * Constructor + */ + RoutingEngine(); + + /** + * Destructor + */ + virtual ~RoutingEngine(); + + /** + * Add a final destination in the system. + * The destinations are segments (@see Transitions @see Crossings) + * @param id + */ + void AddFinalDestinationID(int id); + + /** + * Add a new trip to the system. Individual pedestrian can be assigned a particular trip. + * @param trip + */ + void AddTrip(std::vector<std::string> trip); + + /** + * Return a trip/route with the particular id + * FIXME referenz? + * @param id + * @return + */ + const std::vector<std::string> GetTrip(int id) const; + + /** + * Find the next destination using the appropriate router from + * the collection for the pedestrian ped. + */ + void FindRoute(Pedestrian* ped); + + + /** + * Add a new router to the routing system + * + */ + void AddRouter(Router* router); + + /** + * Return the router with the specified strategy + */ + Router* GetRouter(RoutingStrategy strategy) const; + + /** + * Return the router with the specified id + */ + Router* GetRouter(int id) const; + + /** + * Initialize all routers with the current building object + * @param building + */ + void Init(Building* building); + +private: + /// collections of all routers used + std::vector<Router*> _routersCollection; + /// collection of all trips/routes + std::vector<std::vector<std::string> >_tripsCollection; }; #endif /* ROUTINGENGINE_H_ */ diff --git a/routing/SafestPathRouter.cpp b/routing/SafestPathRouter.cpp index 34912c78ec369fd61d489803035283a7a7e8158e..b579ac71ecdb8b6c07a7a644b9014754aa41eda0 100644 --- a/routing/SafestPathRouter.cpp +++ b/routing/SafestPathRouter.cpp @@ -44,205 +44,207 @@ using namespace std; SafestPathRouter::SafestPathRouter() { - numberOfSubroom=0; - _lastUpdateTime=0; - a=1; - c=1; - b=0; - - // Output to files - _phiFile = new FileHandler("Phi_file.csv"); - // _finalLineEvac = new FileHandler("Evac_File.csv"); - // Output to files - - //_finalLineEvac = new double [numberOfSection]; + numberOfSubroom=0; + _lastUpdateTime=0; + a=1; + c=1; + b=0; + + // Output to files + _phiFile = new FileHandler("Phi_file.csv"); + // _finalLineEvac = new FileHandler("Evac_File.csv"); + // Output to files + + //_finalLineEvac = new double [numberOfSection]; } -SafestPathRouter::~SafestPathRouter() { +SafestPathRouter::~SafestPathRouter() +{ - // Output to files - delete _phiFile; - // delete _finalLineEvac; + // Output to files + delete _phiFile; + // delete _finalLineEvac; } -void SafestPathRouter::Init(Building* building) { - //Load the FDS file info - //handle over to the global router engine - GlobalRouter::Init(building); - - - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* room = _building->GetRoom(i); - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - if(sub->GetType()=="floor") - numberOfSubroom=numberOfSubroom+1; - } - } - - //cout<<numberOfSubroom<<endl; - peopleAtSection = new double [numberOfSubroom]; - squareOfSection = new double [numberOfSubroom]; - dFinalLineOFP = new double [numberOfSubroom]; - dFinalLineEvac = new double [numberOfSubroom]; - dPeopleDensity = new double [numberOfSubroom]; - dFinalLength = new double [numberOfSubroom]; - rR = new double [numberOfSubroom]; - - for (int i = 0; i < numberOfSubroom; ++i) { - peopleAtSection[i]=0.0; - squareOfSection [i]=0.0; - dFinalLineOFP [i]=0.0; - dFinalLineEvac[i]=0.0; - dPeopleDensity [i]=0.0; - dFinalLength [i]=0.0; - rR [i]=0.0; - } - - int n=300; - dPreOFP=new double* [n]; - flo = new int [numberOfSubroom]; - - MappingFloorIDtoIndex(); - // load the matrix from fds - ReadMatrixFromFDS(); - - - // lenthOfSection = new double [numberOfSubroom]; - - //for (int i = 0; i < numberOfSubroom; ++i) { - // rR[i] = new double[numberOfSubroom]; - //for (int i=0; i<numberOfSubroom; i++) - // rR[i]=0; - - - // Print out final distance matrix - // for(int i = 0; i < numberOfSubroom; i++) - // cout << rR[i] << " "; - // cout << endl; - - - // for(int i = 0; i < numberOfSubroom; i++){ - //for(int j = 0; j < numberOfSubroom; j++) - //cout << rR[i] << " "; - - //} +void SafestPathRouter::Init(Building* building) +{ + //Load the FDS file info + //handle over to the global router engine + GlobalRouter::Init(building); + + + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* room = _building->GetRoom(i); + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + if(sub->GetType()=="floor") + numberOfSubroom=numberOfSubroom+1; + } + } + + //cout<<numberOfSubroom<<endl; + peopleAtSection = new double [numberOfSubroom]; + squareOfSection = new double [numberOfSubroom]; + dFinalLineOFP = new double [numberOfSubroom]; + dFinalLineEvac = new double [numberOfSubroom]; + dPeopleDensity = new double [numberOfSubroom]; + dFinalLength = new double [numberOfSubroom]; + rR = new double [numberOfSubroom]; + + for (int i = 0; i < numberOfSubroom; ++i) { + peopleAtSection[i]=0.0; + squareOfSection [i]=0.0; + dFinalLineOFP [i]=0.0; + dFinalLineEvac[i]=0.0; + dPeopleDensity [i]=0.0; + dFinalLength [i]=0.0; + rR [i]=0.0; + } + + int n=300; + dPreOFP=new double* [n]; + flo = new int [numberOfSubroom]; + + MappingFloorIDtoIndex(); + // load the matrix from fds + ReadMatrixFromFDS(); + + + // lenthOfSection = new double [numberOfSubroom]; + + //for (int i = 0; i < numberOfSubroom; ++i) { + // rR[i] = new double[numberOfSubroom]; + //for (int i=0; i<numberOfSubroom; i++) + // rR[i]=0; + + + // Print out final distance matrix + // for(int i = 0; i < numberOfSubroom; i++) + // cout << rR[i] << " "; + // cout << endl; + + + // for(int i = 0; i < numberOfSubroom; i++){ + //for(int j = 0; j < numberOfSubroom; j++) + //cout << rR[i] << " "; + + //} } -int SafestPathRouter::FindExit(Pedestrian* p) { +int SafestPathRouter::FindExit(Pedestrian* p) +{ - if(ComputeSafestPath(p)==-1) { - //Log->Write(" sdfds"); - } - //handle over to the global router engine - return GlobalRouter::FindExit(p); + if(ComputeSafestPath(p)==-1) { + //Log->Write(" sdfds"); + } + //handle over to the global router engine + return GlobalRouter::FindExit(p); } -void SafestPathRouter::UpdateMatrices(){ - - int index=0; - - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* room = _building->GetRoom(i); - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - if(sub->GetType()=="floor") - { - peopleAtSection[index]=sub->GetNumberOfPedestrians(); - index++; - } - } - } - - int index1=0; - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* room = _building->GetRoom(i); - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - if(sub->GetType()=="floor") - { - squareOfSection[index1]=sub->GetArea(); - index1++; - - } - } - } - - // Printing a matrix - // for(int j = 0; j < numberOfSubroom; j++) - // cout << peopleAtSection[j] << " "; - // cout << endl; -/* - - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* room = _building->GetRoom(i); - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - if(sub->GetType()=="floor") - { - peopleAtSection[sub->GetSubRoomID()]=sub->GetNumberOfPedestrians(); - } - } - } - - - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* room = _building->GetRoom(i); - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - if(sub->GetType()=="floor") - { - squareOfSection[sub->GetSubRoomID()]=sub->GetArea(); - - } - } - } -*/ - /* - int index=0; - - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* room = _building->GetRoom(i); - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - if(sub->GetType()=="floor") - { - peopleAtSection[index]=sub->GetNumberOfPedestrians(); - index++; - } - } - } - - int index1=0; - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* room = _building->GetRoom(i); - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - if(sub->GetType()=="floor") - { - squareOfSection[index1]=sub->GetArea(); - index1++; - - } - } - } - */ - /* +void SafestPathRouter::UpdateMatrices() +{ - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* room = _building->GetRoom(i); - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - if(sub->GetType()=="floor") { - lenthOfSection[sub->GetSubRoomID()]=sub->GetArea(); - } - } - } - */ + int index=0; + + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* room = _building->GetRoom(i); + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + if(sub->GetType()=="floor") { + peopleAtSection[index]=sub->GetNumberOfPedestrians(); + index++; + } + } + } + + int index1=0; + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* room = _building->GetRoom(i); + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + if(sub->GetType()=="floor") { + squareOfSection[index1]=sub->GetArea(); + index1++; + + } + } + } + + // Printing a matrix + // for(int j = 0; j < numberOfSubroom; j++) + // cout << peopleAtSection[j] << " "; + // cout << endl; + /* + + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* room = _building->GetRoom(i); + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + if(sub->GetType()=="floor") + { + peopleAtSection[sub->GetSubRoomID()]=sub->GetNumberOfPedestrians(); + } + } + } + + + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* room = _building->GetRoom(i); + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + if(sub->GetType()=="floor") + { + squareOfSection[sub->GetSubRoomID()]=sub->GetArea(); + + } + } + } + */ + /* + int index=0; + + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* room = _building->GetRoom(i); + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + if(sub->GetType()=="floor") + { + peopleAtSection[index]=sub->GetNumberOfPedestrians(); + index++; + } + } + } + + int index1=0; + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* room = _building->GetRoom(i); + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + if(sub->GetType()=="floor") + { + squareOfSection[index1]=sub->GetArea(); + index1++; + + } + } + } + */ + /* + + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* room = _building->GetRoom(i); + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + if(sub->GetType()=="floor") { + lenthOfSection[sub->GetSubRoomID()]=sub->GetArea(); + } + } + } + */ } @@ -257,46 +259,45 @@ int SafestPathRouter::ComputeSafestPath(Pedestrian* p) // if (diff>0.015) return -1; // if((((int)p->GetGlobalTime())%UPDATE_FREQUENCY)!=0) return -1; // - //int next = GetBestDefaultRandomExit(p); - //double distance = _accessPoints[next]->GetDistanceTo(0)+p->GetDistanceToNextTarget(); + //int next = GetBestDefaultRandomExit(p); + //double distance = _accessPoints[next]->GetDistanceTo(0)+p->GetDistanceToNextTarget(); - //for (int i=0; i<path.size(); i++) - // preSub[i]=0; + //for (int i=0; i<path.size(); i++) + // preSub[i]=0; - //Print out final distance matrix - //for(int j = 0; j < numberOfSubroom; j++) - // cout << flo[j] << " "; - //cout << endl; + //Print out final distance matrix + //for(int j = 0; j < numberOfSubroom; j++) + // cout << flo[j] << " "; + //cout << endl; - //Print out final distance matrix - // for(int j = 0; j < numberOfSubroom; j++) - // cout << rR[j] << " "; - // cout << endl; + //Print out final distance matrix + // for(int j = 0; j < numberOfSubroom; j++) + // cout << rR[j] << " "; + // cout << endl; - Room* room = _building->GetRoom(p->GetRoomID()); - SubRoom* sub = room->GetSubRoom(p->GetSubRoomID()); - int best_goal=p->GetFinalDestination(); - double best_phi=14532545; + Room* room = _building->GetRoom(p->GetRoomID()); + SubRoom* sub = room->GetSubRoom(p->GetSubRoomID()); + int best_goal=p->GetFinalDestination(); + double best_phi=14532545; - if(sub->GetType()=="dA") - { + if(sub->GetType()=="dA") { - //eventually write any goal - for (map<int, Goal*>::const_iterator itr = _building->GetAllGoals().begin(); - itr != _building->GetAllGoals().end(); ++itr) { - int goal_current = itr->second->GetId(); + //eventually write any goal + for (map<int, Goal*>::const_iterator itr = _building->GetAllGoals().begin(); + itr != _building->GetAllGoals().end(); ++itr) { + int goal_current = itr->second->GetId(); - double phi_current=0; + double phi_current=0; - // get the path - std::vector<SubRoom*> path; - path.clear(); - GetPath(p, goal_current, path); + // get the path + std::vector<SubRoom*> path; + path.clear(); + GetPath(p, goal_current, path); // for(unsigned int j = 0; j <path.size(); j++) // //if(path[j]->GetType()=="floor") @@ -307,39 +308,36 @@ int SafestPathRouter::ComputeSafestPath(Pedestrian* p) - // compute the cost (adding the phi values) - for(unsigned int j = 0; j <path.size(); j++) - { - if(path[j]->GetType()=="floor") - { - int z=path[j]->GetSubRoomID(); + // compute the cost (adding the phi values) + for(unsigned int j = 0; j <path.size(); j++) { + if(path[j]->GetType()=="floor") { + int z=path[j]->GetSubRoomID(); - for(int j = 0; j <numberOfSubroom; j++) - { - if(flo[j]==z){ - phi_current=phi_current+rR[j]; - } - } + for(int j = 0; j <numberOfSubroom; j++) { + if(flo[j]==z) { + phi_current=phi_current+rR[j]; + } + } - } + } - } - if (phi_current < best_phi) { - best_phi = phi_current; - best_goal= goal_current; - } - //cout <<"value:" <<phi_current<<endl; - // save the goal id for that path if smaller that the previous - } - //cout <<"best phi: "<< best_phi<<endl; - //cout <<"best goal: "<< best_goal<<endl; - //exit(0); - //cout << rR[10]<< endl; - } + } + if (phi_current < best_phi) { + best_phi = phi_current; + best_goal= goal_current; + } + //cout <<"value:" <<phi_current<<endl; + // save the goal id for that path if smaller that the previous + } + //cout <<"best phi: "<< best_phi<<endl; + //cout <<"best goal: "<< best_goal<<endl; + //exit(0); + //cout << rR[10]<< endl; + } - p->SetFinalDestination(best_goal); - p->ClearMentalMap(); + p->SetFinalDestination(best_goal); + p->ClearMentalMap(); @@ -383,14 +381,14 @@ int SafestPathRouter::ComputeSafestPath(Pedestrian* p) -return -1; + return -1; } int SafestPathRouter::GetAgentsCountInSubroom( int roomID, int subroomID) { - return _building->GetRoom(roomID)->GetSubRoom(subroomID)->GetAllPedestrians().size(); + return _building->GetRoom(roomID)->GetSubRoom(subroomID)->GetAllPedestrians().size(); } @@ -398,8 +396,9 @@ int SafestPathRouter::GetAgentsCountInSubroom( int roomID, int subroomID) //todo: use ? -void SafestPathRouter::Initialize(){ - //ReadMatrixFromFDS(); +void SafestPathRouter::Initialize() +{ + //ReadMatrixFromFDS(); } @@ -408,63 +407,61 @@ void SafestPathRouter::Initialize(){ void SafestPathRouter::ReadMatrixFromFDS() { - //double** a; - int m=numberOfSubroom; - int n=300; + //double** a; + int m=numberOfSubroom; + int n=300; - for (int i=0; i<n; i++) - dPreOFP[i]=new double [m]; + for (int i=0; i<n; i++) + dPreOFP[i]=new double [m]; - for (int i=0; i<n; i++) - for (int j=0; j<m; j++) - dPreOFP[i][j]=0; + for (int i=0; i<n; i++) + for (int j=0; j<m; j++) + dPreOFP[i][j]=0; - fstream F; - F.open("OFP2.csv"); + fstream F; + F.open("OFP2.csv"); - if (F) - { - for (int i=0; i<n; i++) - for (int j=0; j<m; j++) - F>>dPreOFP[i][j]; - F.close(); - } + if (F) { + for (int i=0; i<n; i++) + for (int j=0; j<m; j++) + F>>dPreOFP[i][j]; + F.close(); + } - else - { - cout<<"File does not existed"<<endl; - } + else { + cout<<"File does not existed"<<endl; + } - //cout<<a[0][299]<<endl; + //cout<<a[0][299]<<endl; - for (int i=0; i<n; i++) - for (int j=0; j<m; j++) - dPreOFP[i][j]=1-(dPreOFP[i][j]/30); + for (int i=0; i<n; i++) + for (int j=0; j<m; j++) + dPreOFP[i][j]=1-(dPreOFP[i][j]/30); - //for (int i=0; i<n; i++){ - // for (int j=0; j<m; j++) - // cout<<dPreOFP[i][j]<<" "; - // cout<<endl;} + //for (int i=0; i<n; i++){ + // for (int j=0; j<m; j++) + // cout<<dPreOFP[i][j]<<" "; + // cout<<endl;} - int tCurrentStepSize=280; + int tCurrentStepSize=280; - for (int j=0; j<m; j++) - dFinalLineOFP[j]=dPreOFP[tCurrentStepSize][j]; + for (int j=0; j<m; j++) + dFinalLineOFP[j]=dPreOFP[tCurrentStepSize][j]; - //for (int j=0; j<m; j++) - // cout<<dFinalLineOFP[j]<<" "; - //cout<<endl; + //for (int j=0; j<m; j++) + // cout<<dFinalLineOFP[j]<<" "; + //cout<<endl; } @@ -473,43 +470,43 @@ void SafestPathRouter::ReadMatrixFromFDS() void SafestPathRouter::GetHline(Building* building) { - /* + /* - // cout << dFinalLineEvac[j]<< " "; - // cout << endl; - // lenthOfSection + // cout << dFinalLineEvac[j]<< " "; + // cout << endl; + // lenthOfSection - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* room = _building->GetRoom(i); - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - if(sub->GetType()=="floor") { + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* room = _building->GetRoom(i); + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + if(sub->GetType()=="floor") { - for (map<int, Hline*>::const_iterator itr = _building->GetAllHlines().begin(); - itr != _building->GetAllHlines().end(); ++itr) { - //int door=itr->first; - int door = itr->second->GetUniqueID(); - Hline* cross = itr->second; - Point centre = cross->GetCentre(); - double center[2] = { centre.GetX(), centre.GetY() }; + for (map<int, Hline*>::const_iterator itr = _building->GetAllHlines().begin(); + itr != _building->GetAllHlines().end(); ++itr) { + //int door=itr->first; + int door = itr->second->GetUniqueID(); + Hline* cross = itr->second; + Point centre = cross->GetCentre(); + double center[2] = { centre.GetX(), centre.GetY() }; - AccessPoint* ap = new AccessPoint(door, center); - ap->SetNavLine(cross); - char friendlyName[CLENGTH]; - sprintf(friendlyName, "hline_%d_room_%d_subroom_%d", cross->GetID(), - cross->GetRoom()->GetID(), - cross->GetSubRoom()->GetSubRoomID()); - ap->SetFriendlyName(friendlyName); - } + AccessPoint* ap = new AccessPoint(door, center); + ap->SetNavLine(cross); + char friendlyName[CLENGTH]; + sprintf(friendlyName, "hline_%d_room_%d_subroom_%d", cross->GetID(), + cross->GetRoom()->GetID(), + cross->GetSubRoom()->GetSubRoomID()); + ap->SetFriendlyName(friendlyName); + } - } - } - } - */ + } + } + } + */ } @@ -520,217 +517,210 @@ void SafestPathRouter::GetHline(Building* building) void SafestPathRouter::CalculatePhi() { - // Here: - // 0.125 is a square of horizontal people's projection (m2) - // 0.92 is a maximal people's density which do not hurt themselves (m2/m2) (per/m2) - // All of those values can be changed regarding to some conditions + // Here: + // 0.125 is a square of horizontal people's projection (m2) + // 0.92 is a maximal people's density which do not hurt themselves (m2/m2) (per/m2) + // All of those values can be changed regarding to some conditions - for(int j = 0; j < numberOfSubroom; j ++) // - { - dPeopleDensity[j]=peopleAtSection[j]/ squareOfSection[j]; - dFinalLineEvac[j]= (peopleAtSection[j] * 0.125) / (squareOfSection[j] * 0.92); - } + for(int j = 0; j < numberOfSubroom; j ++) { // + dPeopleDensity[j]=peopleAtSection[j]/ squareOfSection[j]; + dFinalLineEvac[j]= (peopleAtSection[j] * 0.125) / (squareOfSection[j] * 0.92); + } - // Printing a matrix - // for(int j = 0; j < numberOfSubroom; j++) - // cout << dPeopleDensity[j]<< " "; - // cout << endl; + // Printing a matrix + // for(int j = 0; j < numberOfSubroom; j++) + // cout << dPeopleDensity[j]<< " "; + // cout << endl; - for(int j = 0; j < numberOfSubroom; j ++) // - { - double max=0; - if (squareOfSection[j] > max) - { - maximalSquare=squareOfSection[j]; + for(int j = 0; j < numberOfSubroom; j ++) { // + double max=0; + if (squareOfSection[j] > max) { + maximalSquare=squareOfSection[j]; - } - //cout << maximalSquare<<endl; - } + } + //cout << maximalSquare<<endl; + } - for(int j = 0; j < numberOfSubroom; j ++) // - { - dFinalLength[j]= squareOfSection[j]/maximalSquare; - } + for(int j = 0; j < numberOfSubroom; j ++) { // + dFinalLength[j]= squareOfSection[j]/maximalSquare; + } - double iNt1[numberOfSubroom]; - double iNt2[numberOfSubroom]; - double iNt3[numberOfSubroom]; - double iNt4[numberOfSubroom]; - double iNt5[numberOfSubroom]; - double iNt6[numberOfSubroom]; - double iNt7[numberOfSubroom]; + double iNt1[numberOfSubroom]; + double iNt2[numberOfSubroom]; + double iNt3[numberOfSubroom]; + double iNt4[numberOfSubroom]; + double iNt5[numberOfSubroom]; + double iNt6[numberOfSubroom]; + double iNt7[numberOfSubroom]; - for (int j=0; j<numberOfSubroom; j++) - { - iNt1[j]= dFinalLineEvac[j] * a; - iNt2[j]= dFinalLineOFP[j] * b; - iNt3[j]= dFinalLength[j] * c; - } + for (int j=0; j<numberOfSubroom; j++) { + iNt1[j]= dFinalLineEvac[j] * a; + iNt2[j]= dFinalLineOFP[j] * b; + iNt3[j]= dFinalLength[j] * c; + } - // Printing a matrix - // for(int j = 0; j < numberOfSubroom; j++) - // cout << iNt1[j]<< " "; - // cout << endl; + // Printing a matrix + // for(int j = 0; j < numberOfSubroom; j++) + // cout << iNt1[j]<< " "; + // cout << endl; - for (int j=0; j<numberOfSubroom; j++) - { - iNt4[j]= iNt1[j] * iNt1[j]; - iNt5[j]= iNt2[j] * iNt2[j]; - iNt6[j]= iNt3[j] * iNt3[j]; - } + for (int j=0; j<numberOfSubroom; j++) { + iNt4[j]= iNt1[j] * iNt1[j]; + iNt5[j]= iNt2[j] * iNt2[j]; + iNt6[j]= iNt3[j] * iNt3[j]; + } - for (int j=0; j<numberOfSubroom; j++) - { - iNt7[j]=iNt4[j] + iNt5[j] + iNt6[j]; - } + for (int j=0; j<numberOfSubroom; j++) { + iNt7[j]=iNt4[j] + iNt5[j] + iNt6[j]; + } - //double xX[numberOfSubroom]; + //double xX[numberOfSubroom]; - for (int j=0; j<numberOfSubroom; j++) - { - rR[j]=sqrt(iNt7[j]); - } + for (int j=0; j<numberOfSubroom; j++) { + rR[j]=sqrt(iNt7[j]); + } - // Printing a matrix - //for(int j = 0; j < numberOfSubroom; j++) - // cout << rR[j]<< " "; - //cout << endl; + // Printing a matrix + //for(int j = 0; j < numberOfSubroom; j++) + // cout << rR[j]<< " "; + //cout << endl; - //double dMatrixPreEvac[3]={0.0125,0.0125,0.00833}; - //double dMatrixPreEvac[11]={0.000574,0.000328,0.000589,0.000651,0.000486,0.003576,0.003576,0.001171,0.000976,0.000221,0.000385}; - //double dMatrixPreEvac[1][11]={0.003575,0.000328,0.003575,0.000651,0.000486,0.003575,0.003575,0.001171,0.000976,0.000221,0.000385}; - //double dMatrixPreEvac[1][11]={0.000573,0.000328,0.000589,0.000651,0.000486,0.003574,0.003575,0.001171,0.000976,0.000221,0.000385}; - //double dMatrixPreEvac[1][11]={0.000573,0.000328,0.000589,0.000651,0.000486,0.003574,0.003575,0.001171,0.000976,0.000221,0.000385}; - //double dMatrixPreEvac[1][11]={0.000573,0.000573,0.000573,0.000573,0.000573,0.000573,0.000573,0.000573,0.000573,0.000573,0.000573}; + //double dMatrixPreEvac[3]={0.0125,0.0125,0.00833}; + //double dMatrixPreEvac[11]={0.000574,0.000328,0.000589,0.000651,0.000486,0.003576,0.003576,0.001171,0.000976,0.000221,0.000385}; + //double dMatrixPreEvac[1][11]={0.003575,0.000328,0.003575,0.000651,0.000486,0.003575,0.003575,0.001171,0.000976,0.000221,0.000385}; + //double dMatrixPreEvac[1][11]={0.000573,0.000328,0.000589,0.000651,0.000486,0.003574,0.003575,0.001171,0.000976,0.000221,0.000385}; + //double dMatrixPreEvac[1][11]={0.000573,0.000328,0.000589,0.000651,0.000486,0.003574,0.003575,0.001171,0.000976,0.000221,0.000385}; + //double dMatrixPreEvac[1][11]={0.000573,0.000573,0.000573,0.000573,0.000573,0.000573,0.000573,0.000573,0.000573,0.000573,0.000573}; } -void SafestPathRouter::PrintInfoToFile() { - - string content; - - for (int j=0; j<numberOfSubroom; j++) - { - char tmp[20]; - sprintf(tmp,"%lf",rR[j]); - //cout<<"tmp: "<<tmp<<endl; - content.append(","); - content.append(tmp); - } - - // cout<<content<<endl; - _phiFile->Write(content.c_str()); - - /* - for (int j=0; j<numberOfSubroom; j++) - { - char tmp[20]; - sprintf(tmp,"%lf",dPeopleDensity[j]); - //cout<<"tmp: "<<tmp<<endl; - content.append(","); - content.append(tmp); - } +void SafestPathRouter::PrintInfoToFile() +{ - // cout<<content<<endl; - _finalLineEvac->Write(content.c_str()); - */ + string content; + + for (int j=0; j<numberOfSubroom; j++) { + char tmp[20]; + sprintf(tmp,"%lf",rR[j]); + //cout<<"tmp: "<<tmp<<endl; + content.append(","); + content.append(tmp); + } + + // cout<<content<<endl; + _phiFile->Write(content.c_str()); + + /* + for (int j=0; j<numberOfSubroom; j++) + { + char tmp[20]; + sprintf(tmp,"%lf",dPeopleDensity[j]); + //cout<<"tmp: "<<tmp<<endl; + content.append(","); + content.append(tmp); + } + + // cout<<content<<endl; + _finalLineEvac->Write(content.c_str()); + */ } -void SafestPathRouter::MappingFloorIDtoIndex(){ +void SafestPathRouter::MappingFloorIDtoIndex() +{ - //map <int, int> flo; + //map <int, int> flo; - int index=0; - for (int i = 0; i < _building->GetNumberOfRooms(); i++) { - Room* room = _building->GetRoom(i); - for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { - SubRoom* sub = room->GetSubRoom(j); - if(sub->GetType()=="floor") - { - flo[index]=sub->GetSubRoomID(); - index++; + int index=0; + for (int i = 0; i < _building->GetNumberOfRooms(); i++) { + Room* room = _building->GetRoom(i); + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + if(sub->GetType()=="floor") { + flo[index]=sub->GetSubRoomID(); + index++; - } - } - } + } + } + } - //Print out final distance matrix - for(int j = 0; j < numberOfSubroom; j++) - cout << flo[j] << " "; - cout << endl; + //Print out final distance matrix + for(int j = 0; j < numberOfSubroom; j++) + cout << flo[j] << " "; + cout << endl; } -void SafestPathRouter::UpdateRRmatrix(Pedestrian* p){ +void SafestPathRouter::UpdateRRmatrix(Pedestrian* p) +{ - //double dFinalLength[1][11]={0.328,0.569,0.328,0.414,0.586,0.328,0.328,1.000,0.276,0.759,0.741}; - //double dFinalLength[11]={0.638,0.569,0.534,0.414,0.586,0.328,0.328,1.000,0.276,0.759,0.741}; - //double dFinalLength[11]={0.666,0.666,1.0}; - //double dFinalLength[1][11]={0.638,0.638,0.638,0.638,0.638,0.638,0.638,0.638,0.638,0.638,0.638}; - //double dFinalLength[1][11]={37.0,33.0,31.0,24.0,34.0,19.0,19.0,58.0,16.0,44.0,43.0}; - //double dFinalLineOFP[numberOfSubroom]; - // Print out final distance matrix - // for(int j = 0; j < numberOfSubroom; j++) - // cout << rR[j] << " "; - // cout << endl; + //double dFinalLength[1][11]={0.328,0.569,0.328,0.414,0.586,0.328,0.328,1.000,0.276,0.759,0.741}; + //double dFinalLength[11]={0.638,0.569,0.534,0.414,0.586,0.328,0.328,1.000,0.276,0.759,0.741}; + //double dFinalLength[11]={0.666,0.666,1.0}; + //double dFinalLength[1][11]={0.638,0.638,0.638,0.638,0.638,0.638,0.638,0.638,0.638,0.638,0.638}; + //double dFinalLength[1][11]={37.0,33.0,31.0,24.0,34.0,19.0,19.0,58.0,16.0,44.0,43.0}; + //double dFinalLineOFP[numberOfSubroom]; + // Print out final distance matrix + // for(int j = 0; j < numberOfSubroom; j++) + // cout << rR[j] << " "; + // cout << endl; - if(p->GetGlobalTime()>=5) - { - rR[10]=1000000; + if(p->GetGlobalTime()>=5) { + rR[10]=1000000; - } + } } void SafestPathRouter::ComputeAndUpdateDestinations( - std::vector<Pedestrian*>& pedestrians) { + std::vector<Pedestrian*>& pedestrians) +{ - int currentTime = pedestrians[0]->GetGlobalTime(); + int currentTime = pedestrians[0]->GetGlobalTime(); - if(currentTime!=_lastUpdateTime) - if((currentTime%UPDATE_FREQUENCY)==0) { + if(currentTime!=_lastUpdateTime) + if((currentTime%UPDATE_FREQUENCY)==0) { - UpdateMatrices(); - CalculatePhi(); - _lastUpdateTime=currentTime; - PrintInfoToFile(); - //cout <<" Updating at : " <<currentTime<<endl; - } + UpdateMatrices(); + CalculatePhi(); + _lastUpdateTime=currentTime; + PrintInfoToFile(); + //cout <<" Updating at : " <<currentTime<<endl; + } - // Update + // Update - for (unsigned int p = 0; p < pedestrians.size(); ++p) { + for (unsigned int p = 0; p < pedestrians.size(); ++p) { - if(ComputeSafestPath(pedestrians[p])==-1) { - //Log->Write(" sdfds"); - } + if(ComputeSafestPath(pedestrians[p])==-1) { + //Log->Write(" sdfds"); + } - //handle over to the global router engine - if (GlobalRouter::FindExit(pedestrians[p]) == -1) { - //Log->Write("\tINFO: \tCould not found a route for pedestrian %d",_allPedestians[p]->GetID()); - //Log->Write("\tINFO: \tHe has reached the target cell"); - _building->DeletePedFromSim(pedestrians[p]); - //exit(EXIT_FAILURE); - } - } + //handle over to the global router engine + if (GlobalRouter::FindExit(pedestrians[p]) == -1) { + //Log->Write("\tINFO: \tCould not found a route for pedestrian %d",_allPedestians[p]->GetID()); + //Log->Write("\tINFO: \tHe has reached the target cell"); + _building->DeletePedFromSim(pedestrians[p]); + //exit(EXIT_FAILURE); + } + } // for (unsigned int p = 0; p < pedestrians.size(); ++p) { // diff --git a/routing/SafestPathRouter.h b/routing/SafestPathRouter.h index 99427dddca29214d9831e52234682d46f4484d30..0441fdf812f57a5c9f9037d8078deb450bfc940c 100644 --- a/routing/SafestPathRouter.h +++ b/routing/SafestPathRouter.h @@ -32,127 +32,127 @@ #include "GlobalRouter.h" class SafestPathRouter: public GlobalRouter { - public: - SafestPathRouter(); - virtual ~SafestPathRouter(); +public: + SafestPathRouter(); + virtual ~SafestPathRouter(); - /** - * @override the method from the global router. - */ - virtual int FindExit(Pedestrian* p); + /** + * @override the method from the global router. + */ + virtual int FindExit(Pedestrian* p); - /* - * Load the fds simulation file and preprocess the input, - * before calling the Init from the Global RouterEngine - */ - virtual void Init(Building* building); + /* + * Load the fds simulation file and preprocess the input, + * before calling the Init from the Global RouterEngine + */ + virtual void Init(Building* building); - /** - * Bypass using - */ - void ComputeAndUpdateDestinations(std::vector<Pedestrian*>& pedestrians); + /** + * Bypass using + */ + void ComputeAndUpdateDestinations(std::vector<Pedestrian*>& pedestrians); - private: - /** - * Compute the safest path for the given pedestrian and update the destination. - * FindExit from the global router is called afterward to perform the navigation - * ONLY the final destination should be updated in this function, as the navigation - * itself is handled by the global router engine - * @return the new safest goalID, -1, if there was an Error - */ - int ComputeSafestPath(Pedestrian* p); +private: + /** + * Compute the safest path for the given pedestrian and update the destination. + * FindExit from the global router is called afterward to perform the navigation + * ONLY the final destination should be updated in this function, as the navigation + * itself is handled by the global router engine + * @return the new safest goalID, -1, if there was an Error + */ + int ComputeSafestPath(Pedestrian* p); - /** - * do some initialisation stuff... - */ - void Initialize(); + /** + * do some initialisation stuff... + */ + void Initialize(); - /** - * Print the phi index in the file - */ + /** + * Print the phi index in the file + */ - void PrintInfoToFile(); + void PrintInfoToFile(); - /** - * reads the results from fds evac - */ - void ReadMatrixFromFDS(); - void GetHline(Building* building); - void UpdateMatrices(); + /** + * reads the results from fds evac + */ + void ReadMatrixFromFDS(); + void GetHline(Building* building); + void UpdateMatrices(); - int GetAgentsCountInSubroom( int roomID, int subroomID); + int GetAgentsCountInSubroom( int roomID, int subroomID); - /** - * - * @param p - */ - void UpdateRRmatrix(Pedestrian* p); + /** + * + * @param p + */ + void UpdateRRmatrix(Pedestrian* p); - void CalculatePhi(); + void CalculatePhi(); - /** - * TODO: investigate the use of a map - */ - void MappingFloorIDtoIndex( ); + /** + * TODO: investigate the use of a map + */ + void MappingFloorIDtoIndex( ); - int MapSection; + int MapSection; - private: - // double dMatrixPreEvac[1][11]; - // double dFinalLength[1][11]; +private: + // double dMatrixPreEvac[1][11]; + // double dFinalLength[1][11]; - // last time the matrices were updated - long int _lastUpdateTime; + // last time the matrices were updated + long int _lastUpdateTime; - double *dFinalLineOFP; - double *dFinalLineEvac; + double *dFinalLineOFP; + double *dFinalLineEvac; - // double dFinalLineOFP[1][11]; + // double dFinalLineOFP[1][11]; - // double *_finalLineEvac; - int numberOfSubroom; - double a; - double b; - double c; + // double *_finalLineEvac; + int numberOfSubroom; + double a; + double b; + double c; - int *preSub; - int *flo; - double maximalSquare; - double *lenthOfSection; - // double rR[1][11]; - double *rR; + int *preSub; + int *flo; + double maximalSquare; + double *lenthOfSection; + // double rR[1][11]; + double *rR; - //double peopleAtSection[1][11]; - double *peopleAtSection; - double *squareOfSection; - double *dFinalLength; - double *dPeopleDensity; - double **dPreOFP; + //double peopleAtSection[1][11]; + double *peopleAtSection; + double *squareOfSection; + double *dFinalLength; + double *dPeopleDensity; + double **dPreOFP; - FileHandler* _phiFile; - FileHandler* _finalLineEvac; + FileHandler* _phiFile; + FileHandler* _finalLineEvac; - // double rR[1][11]; + // double rR[1][11]; - //double peopleAtSection[1][11]; - //double *peopleAtSection; + //double peopleAtSection[1][11]; + //double *peopleAtSection; - // double iNt1[1][11]; - // double iNt2[1][11]; - // double iNt3[1][11]; - // double iNt4[1][11]; + // double iNt1[1][11]; + // double iNt2[1][11]; + // double iNt3[1][11]; + // double iNt4[1][11]; }; diff --git a/routing/Triangulation.h b/routing/Triangulation.h index 8208e8fc5301a6a8bd35bfcf649ae8a484344346..bd771c4fca8f6a9c4feb9ea648a76854bde43887 100644 --- a/routing/Triangulation.h +++ b/routing/Triangulation.h @@ -24,84 +24,86 @@ using std::endl; using std::cout; -template <class C> void FreeClear( C & cntr ) { - for ( typename C::iterator it = cntr.begin(); - it != cntr.end(); ++it ) { - delete * it; - } - cntr.clear(); +template <class C> void FreeClear( C & cntr ) +{ + for ( typename C::iterator it = cntr.begin(); + it != cntr.end(); ++it ) { + delete * it; + } + cntr.clear(); } inline -std::vector<p2t::Triangle*> triangles (){ - int num_points = 0; - double max, min; +std::vector<p2t::Triangle*> triangles () +{ + int num_points = 0; + double max, min; - vector< vector<p2t::Point*> > polylines; - vector<p2t::Point*> polyline; + vector< vector<p2t::Point*> > polylines; + vector<p2t::Point*> polyline; - // Create a simple bounding box - polyline.push_back(new p2t::Point(min,min)); - polyline.push_back(new p2t::Point(min,max)); - polyline.push_back(new p2t::Point(max,max)); - polyline.push_back(new p2t::Point(max,min)); + // Create a simple bounding box + polyline.push_back(new p2t::Point(min,min)); + polyline.push_back(new p2t::Point(min,max)); + polyline.push_back(new p2t::Point(max,max)); + polyline.push_back(new p2t::Point(max,min)); - cout << "Number of constrained edges = " << polyline.size() << endl; - polylines.push_back(polyline); + cout << "Number of constrained edges = " << polyline.size() << endl; + polylines.push_back(polyline); - /* - * Perform triangulation! - */ + /* + * Perform triangulation! + */ - /* - * STEP 1: Create CDT and add primary polyline - * NOTE: polyline must be a simple polygon. The polyline's points - * constitute constrained edges. No repeat points!!! - */ - p2t::CDT* cdt = new p2t::CDT(polyline); + /* + * STEP 1: Create CDT and add primary polyline + * NOTE: polyline must be a simple polygon. The polyline's points + * constitute constrained edges. No repeat points!!! + */ + p2t::CDT* cdt = new p2t::CDT(polyline); - /* - * STEP 2: Add holes or Steiner points if necessary - */ + /* + * STEP 2: Add holes or Steiner points if necessary + */ - vector<p2t::Point*> head_hole ; - cdt->AddHole(head_hole); - // Add chest hole - vector<p2t::Point*> chest_hole; - cdt->AddHole(chest_hole); - polylines.push_back(head_hole); - polylines.push_back(chest_hole); + vector<p2t::Point*> head_hole ; + cdt->AddHole(head_hole); + // Add chest hole + vector<p2t::Point*> chest_hole; + cdt->AddHole(chest_hole); + polylines.push_back(head_hole); + polylines.push_back(chest_hole); - /* - * STEP 3: Triangulate! - */ - cdt->Triangulate(); + /* + * STEP 3: Triangulate! + */ + cdt->Triangulate(); - /// Constrained triangles - std::vector<p2t::Triangle*> triangles; - /// Triangle map - std::list<p2t::Triangle*> map; + /// Constrained triangles + std::vector<p2t::Triangle*> triangles; + /// Triangle map + std::list<p2t::Triangle*> map; - triangles = cdt->GetTriangles(); - map = cdt->GetMap(); + triangles = cdt->GetTriangles(); + map = cdt->GetMap(); - cout << "Number of points = " << num_points << endl; - cout << "Number of triangles = " << triangles.size() << endl; + cout << "Number of points = " << num_points << endl; + cout << "Number of triangles = " << triangles.size() << endl; - // Free points - for(unsigned int i = 0; i < polylines.size(); i++) { - vector<p2t::Point*> poly = polylines[i]; - FreeClear(poly); - } + // Free points + for(unsigned int i = 0; i < polylines.size(); i++) { + vector<p2t::Point*> poly = polylines[i]; + FreeClear(poly); + } - // delete cdt; - return triangles; + // delete cdt; + return triangles; } #endif /* TRIANGULATION_H_ */ diff --git a/routing/cognitive_map/AbstractCognitiveMapCreator.h b/routing/cognitive_map/AbstractCognitiveMapCreator.h index 4bad4335aa99f70b46c5e749a2ab9876ad059913..581e18c101d17083723ddc53df88150b6e5d456a 100644 --- a/routing/cognitive_map/AbstractCognitiveMapCreator.h +++ b/routing/cognitive_map/AbstractCognitiveMapCreator.h @@ -15,16 +15,15 @@ class CognitiveMap; -class AbstractCognitiveMapCreator -{ - public: - AbstractCognitiveMapCreator(const Building * b) : building(b) {} +class AbstractCognitiveMapCreator { +public: + AbstractCognitiveMapCreator(const Building * b) : building(b) {} - virtual ~AbstractCognitiveMapCreator(); - virtual CognitiveMap * CreateCognitiveMap(const Pedestrian * ped) = 0; - protected: - const Building * const building; + virtual ~AbstractCognitiveMapCreator(); + virtual CognitiveMap * CreateCognitiveMap(const Pedestrian * ped) = 0; +protected: + const Building * const building; }; #endif // ABSTRACTCOGNITIVEMAPCREATOR_H diff --git a/routing/cognitive_map/CognitiveMap.cpp b/routing/cognitive_map/CognitiveMap.cpp index 5924ee244951683a7292c053854d6a5c0beca39e..6ed5c763e50978bd9bf48c26fae06c18fa6dd09d 100644 --- a/routing/cognitive_map/CognitiveMap.cpp +++ b/routing/cognitive_map/CognitiveMap.cpp @@ -23,55 +23,55 @@ using namespace std; */ CognitiveMap::CognitiveMap(const Building * building, const Pedestrian * pedestrian) - : building(building), pedestrian(pedestrian) + : building(building), pedestrian(pedestrian) { - navigation_graph = new NavigationGraph(building); + navigation_graph = new NavigationGraph(building); } CognitiveMap::~CognitiveMap() { - delete navigation_graph; + delete navigation_graph; } void CognitiveMap::Add(const SubRoom * sub_room) { - navigation_graph->AddVertex(sub_room); + navigation_graph->AddVertex(sub_room); } void CognitiveMap::Add(const Crossing * crossing) { - navigation_graph->AddEdge(crossing); + navigation_graph->AddEdge(crossing); } void CognitiveMap::AddExit(const Transition * exit) { - navigation_graph->AddExit(exit); + navigation_graph->AddExit(exit); } NavigationGraph::VerticesContainer * CognitiveMap::GetAllVertices() { - return navigation_graph->GetAllVertices(); + return navigation_graph->GetAllVertices(); } const NavigationGraph * CognitiveMap::GetNavigationGraph() const { - return navigation_graph; + return navigation_graph; } const NavLine * CognitiveMap::GetDestination() { - SubRoom * sub_room = building->GetRoom(pedestrian->GetRoomID())->GetSubRoom(pedestrian->GetSubRoomID()); + SubRoom * sub_room = building->GetRoom(pedestrian->GetRoomID())->GetSubRoom(pedestrian->GetSubRoomID()); - std::pair<const GraphEdge*, double> cheapest_destination = (*navigation_graph)[sub_room]->GetCheapestDestinationByEdges(pedestrian->GetPos()); + std::pair<const GraphEdge*, double> cheapest_destination = (*navigation_graph)[sub_room]->GetCheapestDestinationByEdges(pedestrian->GetPos()); - if(cheapest_destination.first != NULL) { - return cheapest_destination.first->GetCrossing(); - } else { - return NULL; - } + if(cheapest_destination.first != NULL) { + return cheapest_destination.first->GetCrossing(); + } else { + return NULL; + } } const NavLine * CognitiveMap::GetLocalDestination() { - return NULL; + return NULL; } diff --git a/routing/cognitive_map/CognitiveMap.h b/routing/cognitive_map/CognitiveMap.h index d3fb08c946d8589953264d6ef889b80ce40d00a5..3a512db7bd066174b3c9d47724fefabc690750c5 100644 --- a/routing/cognitive_map/CognitiveMap.h +++ b/routing/cognitive_map/CognitiveMap.h @@ -30,28 +30,28 @@ class Pedestrian; */ class CognitiveMap { - public: - /**************************** - * Constructors & Destructors - ****************************/ - CognitiveMap(const Building * building, const Pedestrian * pedestrian); - virtual ~CognitiveMap(); +public: + /**************************** + * Constructors & Destructors + ****************************/ + CognitiveMap(const Building * building, const Pedestrian * pedestrian); + virtual ~CognitiveMap(); - void Add(const SubRoom * sub_room); - void Add(const Crossing * crossing); - void AddExit(const Transition * exit); + void Add(const SubRoom * sub_room); + void Add(const Crossing * crossing); + void AddExit(const Transition * exit); - NavigationGraph::VerticesContainer * GetAllVertices(); + NavigationGraph::VerticesContainer * GetAllVertices(); - const NavigationGraph * GetNavigationGraph() const; + const NavigationGraph * GetNavigationGraph() const; - const NavLine * GetDestination(); - const NavLine * GetLocalDestination(); + const NavLine * GetDestination(); + const NavLine * GetLocalDestination(); - private: - NavigationGraph * navigation_graph; - const Building * const building; - const Pedestrian * const pedestrian; +private: + NavigationGraph * navigation_graph; + const Building * const building; + const Pedestrian * const pedestrian; }; diff --git a/routing/cognitive_map/CognitiveMapStorage.cpp b/routing/cognitive_map/CognitiveMapStorage.cpp index e6090ca02bed2a7e080ba0ff2622beb7f6830310..f4ae5c50fe3a61755cdde5ce88ed7fe4c2a52f5d 100644 --- a/routing/cognitive_map/CognitiveMapStorage.cpp +++ b/routing/cognitive_map/CognitiveMapStorage.cpp @@ -18,13 +18,13 @@ CognitiveMapStorage::CognitiveMapStorage(const Building * const b) : building(b) { - //creator = new EmptyCognitiveMapCreator(b); - creator = new CompleteCognitiveMapCreator(b); + //creator = new EmptyCognitiveMapCreator(b); + creator = new CompleteCognitiveMapCreator(b); } CognitiveMapStorage::~CognitiveMapStorage() { - delete creator; + delete creator; } CMStorageValueType CognitiveMapStorage::operator[] (CMStorageKeyType key) @@ -39,9 +39,9 @@ CMStorageValueType CognitiveMapStorage::operator[] (CMStorageKeyType key) void CognitiveMapStorage::CreateCognitiveMap(CMStorageKeyType ped) { - //todo: the possibility to have more then one creator. - cognitive_maps.emplace(ped, creator->CreateCognitiveMap(ped)); + //todo: the possibility to have more then one creator. + cognitive_maps.emplace(ped, creator->CreateCognitiveMap(ped)); - //debug - //cognitive_maps[ped]->GetNavigationGraph()->WriteToDotFile(building->GetProjectRootDir()); + //debug + //cognitive_maps[ped]->GetNavigationGraph()->WriteToDotFile(building->GetProjectRootDir()); } diff --git a/routing/cognitive_map/CognitiveMapStorage.h b/routing/cognitive_map/CognitiveMapStorage.h index 3a63705e21253ddb9cd6145a6912f6880db254d7..88368791530592ca714cab3f227dbac7698dbe7c 100644 --- a/routing/cognitive_map/CognitiveMapStorage.h +++ b/routing/cognitive_map/CognitiveMapStorage.h @@ -30,21 +30,21 @@ typedef std::unordered_map<CMStorageKeyType, CMStorageValueType> CMStorageType; * */ class CognitiveMapStorage { - public: - CognitiveMapStorage(const Building * const b); - virtual ~CognitiveMapStorage(); +public: + CognitiveMapStorage(const Building * const b); + virtual ~CognitiveMapStorage(); - CMStorageValueType operator[] (CMStorageKeyType key); + CMStorageValueType operator[] (CMStorageKeyType key); - private: - const Building * const building; - CMStorageType cognitive_maps; - AbstractCognitiveMapCreator * creator; +private: + const Building * const building; + CMStorageType cognitive_maps; + AbstractCognitiveMapCreator * creator; - void CreateCognitiveMap(CMStorageKeyType ped); + void CreateCognitiveMap(CMStorageKeyType ped); }; diff --git a/routing/cognitive_map/CompleteCognitiveMapCreator.cpp b/routing/cognitive_map/CompleteCognitiveMapCreator.cpp index 5c17d6f37b67c0f8377e54f9bdeec19dad40b6a5..5cf6a4d42c29aa873e19ab904af3e325bfa80d2d 100644 --- a/routing/cognitive_map/CompleteCognitiveMapCreator.cpp +++ b/routing/cognitive_map/CompleteCognitiveMapCreator.cpp @@ -17,39 +17,35 @@ CompleteCognitiveMapCreator::~CompleteCognitiveMapCreator() { - return; + return; } CognitiveMap * CompleteCognitiveMapCreator::CreateCognitiveMap(const Pedestrian * ped) { - CognitiveMap * cm = new CognitiveMap(building, ped); + CognitiveMap * cm = new CognitiveMap(building, ped); - //adding all SubRooms as Vertex - const std::vector<Room *>& rooms = building->GetAllRooms(); - for(std::vector<Room *>::const_iterator it = rooms.begin(); it != rooms.end(); ++it) - { - const std::vector<SubRoom *>& sub_rooms = (*it)->GetAllSubRooms(); - for(std::vector<SubRoom *>::const_iterator it = sub_rooms.begin(); it != sub_rooms.end(); ++it) - { - cm->Add((*it)); - } - } - //Add crossings as edges - const std::map<int, Crossing *>& crossings = building->GetAllCrossings(); - for(std::map<int, Crossing*>::const_iterator it = crossings.begin(); it != crossings.end(); ++it) - { - cm->Add(it->second); - } - //Add transitions as edges - const std::map<int, Transition *>& transitions = building->GetAllTransitions(); - for(std::map<int, Transition *>::const_iterator it = transitions.begin(); it != transitions.end(); ++it) - { - if(it->second->IsExit()) { - cm->AddExit(it->second); - } else { - cm->Add(it->second); - } - } + //adding all SubRooms as Vertex + const std::vector<Room *>& rooms = building->GetAllRooms(); + for(std::vector<Room *>::const_iterator it = rooms.begin(); it != rooms.end(); ++it) { + const std::vector<SubRoom *>& sub_rooms = (*it)->GetAllSubRooms(); + for(std::vector<SubRoom *>::const_iterator it = sub_rooms.begin(); it != sub_rooms.end(); ++it) { + cm->Add((*it)); + } + } + //Add crossings as edges + const std::map<int, Crossing *>& crossings = building->GetAllCrossings(); + for(std::map<int, Crossing*>::const_iterator it = crossings.begin(); it != crossings.end(); ++it) { + cm->Add(it->second); + } + //Add transitions as edges + const std::map<int, Transition *>& transitions = building->GetAllTransitions(); + for(std::map<int, Transition *>::const_iterator it = transitions.begin(); it != transitions.end(); ++it) { + if(it->second->IsExit()) { + cm->AddExit(it->second); + } else { + cm->Add(it->second); + } + } - return cm; + return cm; } diff --git a/routing/cognitive_map/CompleteCognitiveMapCreator.h b/routing/cognitive_map/CompleteCognitiveMapCreator.h index 46df1549dfadfba0ddacda304f4d246933a06c08..1a2f06caadf64e8df68df6e9d1e4c981a404ffe5 100644 --- a/routing/cognitive_map/CompleteCognitiveMapCreator.h +++ b/routing/cognitive_map/CompleteCognitiveMapCreator.h @@ -16,16 +16,15 @@ class Building; -class CompleteCognitiveMapCreator : public AbstractCognitiveMapCreator -{ +class CompleteCognitiveMapCreator : public AbstractCognitiveMapCreator { - public: - CompleteCognitiveMapCreator(const Building * b) : AbstractCognitiveMapCreator(b) { } +public: + CompleteCognitiveMapCreator(const Building * b) : AbstractCognitiveMapCreator(b) { } - virtual ~CompleteCognitiveMapCreator(); + virtual ~CompleteCognitiveMapCreator(); - CognitiveMap * CreateCognitiveMap(const Pedestrian * ped); - private: + CognitiveMap * CreateCognitiveMap(const Pedestrian * ped); +private: }; diff --git a/routing/cognitive_map/EmptyCognitiveMapCreator.cpp b/routing/cognitive_map/EmptyCognitiveMapCreator.cpp index f78960c1f09b4a56716ac4a51c0eac31ccd04036..b521d9deab74318d49a03d156a0325430942b82f 100644 --- a/routing/cognitive_map/EmptyCognitiveMapCreator.cpp +++ b/routing/cognitive_map/EmptyCognitiveMapCreator.cpp @@ -17,12 +17,12 @@ EmptyCognitiveMapCreator::~EmptyCognitiveMapCreator() { - return; + return; } CognitiveMap * EmptyCognitiveMapCreator::CreateCognitiveMap(const Pedestrian * ped) { - CognitiveMap * cm = new CognitiveMap(building, ped); + CognitiveMap * cm = new CognitiveMap(building, ped); - return cm; + return cm; } diff --git a/routing/cognitive_map/EmptyCognitiveMapCreator.h b/routing/cognitive_map/EmptyCognitiveMapCreator.h index 69d30459d42b20e7244ce658a5e8b47e649ee529..278ff2fd7a4d185d267b6346bb6cd3402bc0efe4 100644 --- a/routing/cognitive_map/EmptyCognitiveMapCreator.h +++ b/routing/cognitive_map/EmptyCognitiveMapCreator.h @@ -16,16 +16,15 @@ class Building; -class EmptyCognitiveMapCreator : public AbstractCognitiveMapCreator -{ +class EmptyCognitiveMapCreator : public AbstractCognitiveMapCreator { - public: - EmptyCognitiveMapCreator(const Building * b) : AbstractCognitiveMapCreator(b) { } +public: + EmptyCognitiveMapCreator(const Building * b) : AbstractCognitiveMapCreator(b) { } - virtual ~EmptyCognitiveMapCreator(); + virtual ~EmptyCognitiveMapCreator(); - CognitiveMap * CreateCognitiveMap(const Pedestrian * ped); - private: + CognitiveMap * CreateCognitiveMap(const Pedestrian * ped); +private: }; diff --git a/routing/cognitive_map/NavigationGraph.cpp b/routing/cognitive_map/NavigationGraph.cpp index d82692ddfd0d53c76b2290cb1170078de849b7b1..848cc5f7ce51fe852d0b8520ae293d3eaaec705b 100644 --- a/routing/cognitive_map/NavigationGraph.cpp +++ b/routing/cognitive_map/NavigationGraph.cpp @@ -23,87 +23,84 @@ */ NavigationGraph::NavigationGraph(const Building * building) - : building(building) + : building(building) { } NavigationGraph::NavigationGraph(const NavigationGraph & ng) - : building(ng.building) + : building(ng.building) { } NavigationGraph::~NavigationGraph() { - //remove all vertices - for(VerticesContainer::iterator it = vertices.begin(); it != vertices.end(); ++it) - { - delete it->second; - } + //remove all vertices + for(VerticesContainer::iterator it = vertices.begin(); it != vertices.end(); ++it) { + delete it->second; + } } void NavigationGraph::AddVertex(const SubRoom * const sub_room) { - vertices.insert(std::pair<const SubRoom *, GraphVertex*>(sub_room, new GraphVertex(sub_room))); + vertices.insert(std::pair<const SubRoom *, GraphVertex*>(sub_room, new GraphVertex(sub_room))); } void NavigationGraph::AddEdge(const Crossing * crossing) { - VerticesContainer::iterator src_it = vertices.find(crossing->GetSubRoom1()); - VerticesContainer::iterator dest_it = vertices.find(crossing->GetSubRoom2()); - - if(src_it != vertices.end() && dest_it != vertices.end()) - { - src_it->second->AddOutEdge(dest_it->second, crossing); - dest_it->second->AddOutEdge(src_it->second, crossing); - } + VerticesContainer::iterator src_it = vertices.find(crossing->GetSubRoom1()); + VerticesContainer::iterator dest_it = vertices.find(crossing->GetSubRoom2()); + + if(src_it != vertices.end() && dest_it != vertices.end()) { + src_it->second->AddOutEdge(dest_it->second, crossing); + dest_it->second->AddOutEdge(src_it->second, crossing); + } } void NavigationGraph::AddExit(const Transition * transition) { - VerticesContainer::iterator src_it = vertices.find(transition->GetSubRoom1()); - if(src_it != vertices.end()) { - src_it->second->AddExit(transition); - } + VerticesContainer::iterator src_it = vertices.find(transition->GetSubRoom1()); + if(src_it != vertices.end()) { + src_it->second->AddExit(transition); + } } GraphVertex * NavigationGraph::operator[](const SubRoom * const sub_room) { - VerticesContainer::iterator it = vertices.find(sub_room); - if(it == vertices.end()) { - AddVertex(sub_room); - } - return vertices[sub_room]; + VerticesContainer::iterator it = vertices.find(sub_room); + if(it == vertices.end()) { + AddVertex(sub_room); + } + return vertices[sub_room]; } NavigationGraph::VerticesContainer * NavigationGraph::GetAllVertices() { - return & vertices; + return & vertices; } void NavigationGraph::WriteToDotFile(const std :: string filepath) const { - std::ofstream dot_file; - dot_file.open (filepath + "navigation_graph.dot"); - dot_file << " digraph graphname \n {\n"; - for(VerticesContainer::const_iterator it = vertices.begin(); it != vertices.end(); ++it) { - dot_file << it->second->GetCaption(); - dot_file << " [ \n pos =\"" + std::to_string(it->second->GetSubRoom()->GetCentroid().GetX()) +"," + std::to_string(it->second->GetSubRoom()->GetCentroid().GetY()) +"!\"\n shape=box \n"; - if(it->second->HasExit()) - dot_file << "style=filled, color=red\n"; - - dot_file << "]\n" ; - const GraphVertex::EdgesContainer * edges = it->second->GetAllOutEdges(); - for(GraphVertex::EdgesContainer::const_iterator it2 = edges->begin(); it2 != edges->end(); ++it2) - { - if(!(*it2)->GetCrossing()->IsExit()) { - dot_file << it->second->GetCaption() + " -> " + (*it2)->GetDest()->GetCaption() + "\n ["; - dot_file << "label = "+ std::to_string((*it2)->GetWeight(it->second->GetSubRoom()->GetCentroid())) + "] \n"; - } - } - - } - dot_file << "} \n"; - - dot_file.close(); - return; + std::ofstream dot_file; + dot_file.open (filepath + "navigation_graph.dot"); + dot_file << " digraph graphname \n {\n"; + for(VerticesContainer::const_iterator it = vertices.begin(); it != vertices.end(); ++it) { + dot_file << it->second->GetCaption(); + dot_file << " [ \n pos =\"" + std::to_string(it->second->GetSubRoom()->GetCentroid().GetX()) +"," + std::to_string(it->second->GetSubRoom()->GetCentroid().GetY()) +"!\"\n shape=box \n"; + if(it->second->HasExit()) + dot_file << "style=filled, color=red\n"; + + dot_file << "]\n" ; + const GraphVertex::EdgesContainer * edges = it->second->GetAllOutEdges(); + for(GraphVertex::EdgesContainer::const_iterator it2 = edges->begin(); it2 != edges->end(); ++it2) { + if(!(*it2)->GetCrossing()->IsExit()) { + dot_file << it->second->GetCaption() + " -> " + (*it2)->GetDest()->GetCaption() + "\n ["; + dot_file << "label = "+ std::to_string((*it2)->GetWeight(it->second->GetSubRoom()->GetCentroid())) + "] \n"; + } + } + + } + dot_file << "} \n"; + + dot_file.close(); + return; } diff --git a/routing/cognitive_map/NavigationGraph.h b/routing/cognitive_map/NavigationGraph.h index 5bca7bce320970ccce1ebf7523c7e8c43cfdab00..fcb4665ee6bc895e47704901c0a4bf954f31c7c0 100644 --- a/routing/cognitive_map/NavigationGraph.h +++ b/routing/cognitive_map/NavigationGraph.h @@ -34,34 +34,34 @@ class Transition; */ class NavigationGraph { - public: - typedef std::unordered_map<const SubRoom * , GraphVertex *> VerticesContainer; +public: + typedef std::unordered_map<const SubRoom * , GraphVertex *> VerticesContainer; - /**************************** - * Constructors & Destructors - ****************************/ - NavigationGraph(const Building * building); - NavigationGraph(const NavigationGraph & ng); + /**************************** + * Constructors & Destructors + ****************************/ + NavigationGraph(const Building * building); + NavigationGraph(const NavigationGraph & ng); - virtual ~NavigationGraph(); + virtual ~NavigationGraph(); - void AddVertex(const SubRoom * const sub_room); - void AddEdge(const Crossing * crossing); - void AddExit(const Transition * transition); + void AddVertex(const SubRoom * const sub_room); + void AddEdge(const Crossing * crossing); + void AddExit(const Transition * transition); - GraphVertex * operator[](const SubRoom * const sub_room); + GraphVertex * operator[](const SubRoom * const sub_room); - NavigationGraph::VerticesContainer * GetAllVertices(); + NavigationGraph::VerticesContainer * GetAllVertices(); - void WriteToDotFile(const std::string filepath) const; + void WriteToDotFile(const std::string filepath) const; - private: - /** - * Vertices and Edges - */ - NavigationGraph::VerticesContainer vertices; - const Building * const building; +private: + /** + * Vertices and Edges + */ + NavigationGraph::VerticesContainer vertices; + const Building * const building; }; diff --git a/routing/cognitive_map/navigation_graph/GraphEdge.cpp b/routing/cognitive_map/navigation_graph/GraphEdge.cpp index 15782c6d4290c28b489cdb650774c372730692e0..0a78fde8962e98078d0dd6c642366aa21b5802ab 100644 --- a/routing/cognitive_map/navigation_graph/GraphEdge.cpp +++ b/routing/cognitive_map/navigation_graph/GraphEdge.cpp @@ -24,60 +24,60 @@ using namespace std; GraphEdge::~GraphEdge() { - return; + return; } GraphEdge::GraphEdge(const GraphVertex * const s, const GraphVertex * const d, const Crossing * const crossing) - : src(s), dest(d), crossing(crossing) + : src(s), dest(d), crossing(crossing) { - CalcApproximateDistance(); + CalcApproximateDistance(); } GraphEdge::GraphEdge(GraphEdge const &ge) - : src(ge.src), dest(ge.dest), crossing(ge.crossing), approximate_distance(ge.approximate_distance) + : src(ge.src), dest(ge.dest), crossing(ge.crossing), approximate_distance(ge.approximate_distance) { } void GraphEdge::CalcApproximateDistance() { - double distance = 0.0; - int count = 0; - for(std::vector<Crossing*>::const_iterator it = src->GetSubRoom()->GetAllCrossings().begin(); it != src->GetSubRoom()->GetAllCrossings().end(); ++it) { - if(crossing->GetUniqueID() == (*it)->GetUniqueID()) continue; - if(GetDest() != NULL && ((*it)->GetSubRoom1() == GetDest()->GetSubRoom() || (*it)->GetSubRoom2() == GetDest()->GetSubRoom())) continue; - count++; - distance = distance + (((*it)->GetCentre() - crossing->GetCentre()).Norm()); - } - - for(std::vector<Transition*>::const_iterator it = src->GetSubRoom()->GetAllTransitions().begin(); it != src->GetSubRoom()->GetAllTransitions().end(); ++it) { - if(crossing->GetUniqueID() == (*it)->GetUniqueID()) continue; - if(GetDest() != NULL && ((*it)->GetSubRoom1() == GetDest()->GetSubRoom() || (*it)->GetSubRoom2() == GetDest()->GetSubRoom())) continue; - count++; - distance = distance + (((*it)->GetCentre() - crossing->GetCentre()).Norm()); - } - if(count == 0) approximate_distance = 0; - else approximate_distance = distance/count; + double distance = 0.0; + int count = 0; + for(std::vector<Crossing*>::const_iterator it = src->GetSubRoom()->GetAllCrossings().begin(); it != src->GetSubRoom()->GetAllCrossings().end(); ++it) { + if(crossing->GetUniqueID() == (*it)->GetUniqueID()) continue; + if(GetDest() != NULL && ((*it)->GetSubRoom1() == GetDest()->GetSubRoom() || (*it)->GetSubRoom2() == GetDest()->GetSubRoom())) continue; + count++; + distance = distance + (((*it)->GetCentre() - crossing->GetCentre()).Norm()); + } + + for(std::vector<Transition*>::const_iterator it = src->GetSubRoom()->GetAllTransitions().begin(); it != src->GetSubRoom()->GetAllTransitions().end(); ++it) { + if(crossing->GetUniqueID() == (*it)->GetUniqueID()) continue; + if(GetDest() != NULL && ((*it)->GetSubRoom1() == GetDest()->GetSubRoom() || (*it)->GetSubRoom2() == GetDest()->GetSubRoom())) continue; + count++; + distance = distance + (((*it)->GetCentre() - crossing->GetCentre()).Norm()); + } + if(count == 0) approximate_distance = 0; + else approximate_distance = distance/count; } double GraphEdge::GetWeight(const Point & position) const { - if(factors.empty()) { - return GetApproximateDistance(position); - } - double weight = GetApproximateDistance(position); + if(factors.empty()) { + return GetApproximateDistance(position); + } + double weight = GetApproximateDistance(position); - for(FactorContainer::const_iterator it = factors.begin(); it != factors.end(); ++it) { - weight = weight * it->second.first; - } + for(FactorContainer::const_iterator it = factors.begin(); it != factors.end(); ++it) { + weight = weight * it->second.first; + } - return weight; + return weight; } void GraphEdge::SetFactor(double factor, std::string name) { - //TODO: set global time as second double - factors[name] = std::make_pair(factor, 0.0); + //TODO: set global time as second double + factors[name] = std::make_pair(factor, 0.0); } @@ -88,36 +88,36 @@ void GraphEdge::SetFactor(double factor, std::string name) double GraphEdge::GetRoomToFloorFactor() const { - if(GetDest() == NULL || GetDest()->GetSubRoom()->GetType() == GetSrc()->GetSubRoom()->GetType()) return 1.0; - if(GetDest()->GetSubRoom()->GetType() == "floor") return 1.0; - else return 5.0; + if(GetDest() == NULL || GetDest()->GetSubRoom()->GetType() == GetSrc()->GetSubRoom()->GetType()) return 1.0; + if(GetDest()->GetSubRoom()->GetType() == "floor") return 1.0; + else return 5.0; } double GraphEdge::GetApproximateDistance(const Point & position) const { - return (crossing->GetCentre()-position).Norm(); + return (crossing->GetCentre()-position).Norm(); } double GraphEdge::GetApproximateDistance() const { - return approximate_distance; + return approximate_distance; } const GraphVertex * GraphEdge::GetDest() const { - return dest; + return dest; } const GraphVertex * GraphEdge::GetSrc() const { - return src; + return src; } const Crossing * GraphEdge::GetCrossing() const { - return crossing; + return crossing; } bool GraphEdge::IsExit() const { - return crossing->IsExit(); + return crossing->IsExit(); } diff --git a/routing/cognitive_map/navigation_graph/GraphEdge.h b/routing/cognitive_map/navigation_graph/GraphEdge.h index 6ef3565090f52d8a16515a08c802111ca74f9b62..f90d1c564bb4f8f6f645ae313ce3c23b3f9d1643 100644 --- a/routing/cognitive_map/navigation_graph/GraphEdge.h +++ b/routing/cognitive_map/navigation_graph/GraphEdge.h @@ -23,57 +23,57 @@ class Crossing; class GraphEdge { - public: - typedef std::map<std::string, std::pair<double, double>> FactorContainer; +public: + typedef std::map<std::string, std::pair<double, double>> FactorContainer; - /**************************** - * Constructors & Destructors - ****************************/ + /**************************** + * Constructors & Destructors + ****************************/ - GraphEdge(const GraphVertex * const s, const GraphVertex * const d, const Crossing * const crossing); - GraphEdge(GraphEdge const & ge); - virtual ~GraphEdge(); + GraphEdge(const GraphVertex * const s, const GraphVertex * const d, const Crossing * const crossing); + GraphEdge(GraphEdge const & ge); + virtual ~GraphEdge(); - void CalcApproximateDistance(); + void CalcApproximateDistance(); - // Getter collection - const GraphVertex * GetDest() const; - const GraphVertex * GetSrc() const; - const Crossing * GetCrossing() const; + // Getter collection + const GraphVertex * GetDest() const; + const GraphVertex * GetSrc() const; + const Crossing * GetCrossing() const; - double GetApproximateDistance() const; - double GetApproximateDistance(const Point &) const; + double GetApproximateDistance() const; + double GetApproximateDistance(const Point &) const; - void SetFactor(double factor, std::string name); + void SetFactor(double factor, std::string name); - double GetRoomToFloorFactor() const; + double GetRoomToFloorFactor() const; - double GetWeight(const Point &) const; + double GetWeight(const Point &) const; - bool IsExit() const; + bool IsExit() const; - private: - const GraphVertex * const src; - const GraphVertex * const dest; - const Crossing * const crossing; +private: + const GraphVertex * const src; + const GraphVertex * const dest; + const Crossing * const crossing; - /** - * Factor Bag - * - * The Factor map is filled up by sensors. The key string is for identification while sharing information. - * The second pair value is the GlobalTime value from Pedestrian Class of this information. - * For calculating the weight we just iterate over the factors and dont care which factors we acutally use. - */ - FactorContainer factors; + /** + * Factor Bag + * + * The Factor map is filled up by sensors. The key string is for identification while sharing information. + * The second pair value is the GlobalTime value from Pedestrian Class of this information. + * For calculating the weight we just iterate over the factors and dont care which factors we acutally use. + */ + FactorContainer factors; - //WEIGHTS DEPRECATED! - double approximate_distance; - double density = 0.0; + //WEIGHTS DEPRECATED! + double approximate_distance; + double density = 0.0; }; diff --git a/routing/cognitive_map/navigation_graph/GraphVertex.cpp b/routing/cognitive_map/navigation_graph/GraphVertex.cpp index dff75ea1d11be41173dc625db68abd95054e7d87..579157c1ad89e044a8bb93d3985f536017c78a39 100644 --- a/routing/cognitive_map/navigation_graph/GraphVertex.cpp +++ b/routing/cognitive_map/navigation_graph/GraphVertex.cpp @@ -27,81 +27,80 @@ using namespace std; */ GraphVertex::GraphVertex(const SubRoom * const sr) - : sub_room(sr) + : sub_room(sr) { } GraphVertex::GraphVertex(GraphVertex const & gv) - : sub_room(gv.sub_room) + : sub_room(gv.sub_room) { } GraphVertex::~GraphVertex() { - return; + return; } void GraphVertex::AddOutEdge(const GraphVertex * const dest, const Crossing * const crossing) { - out_edges.insert(new GraphEdge(this, dest, crossing)); - return; + out_edges.insert(new GraphEdge(this, dest, crossing)); + return; } void GraphVertex::AddExit(const Transition * transition) { - out_edges.insert(new GraphEdge(this, NULL, transition)); - return; + out_edges.insert(new GraphEdge(this, NULL, transition)); + return; } int GraphVertex::RemoveOutEdge(GraphEdge * edge) { - EdgesContainer::iterator it = out_edges.find(edge); - if(it != out_edges.end()) { - delete (*it); - out_edges.erase(it); - return 1; - } - return 0; + EdgesContainer::iterator it = out_edges.find(edge); + if(it != out_edges.end()) { + delete (*it); + out_edges.erase(it); + return 1; + } + return 0; } int GraphVertex::RemoveOutEdge(const GraphVertex * dest) { - //return out_edges.erase(dest); - return 1; + //return out_edges.erase(dest); + return 1; } const std::string GraphVertex::GetCaption() const { - return std::to_string(sub_room->GetRoomID()) + "" + std::to_string(sub_room->GetSubRoomID()); + return std::to_string(sub_room->GetRoomID()) + "" + std::to_string(sub_room->GetSubRoomID()); } const GraphVertex::EdgesContainer * GraphVertex::GetAllOutEdges() const { - return &out_edges; + return &out_edges; } GraphVertex::EdgesContainer * GraphVertex::GetAllEdges() { - return &out_edges; + return &out_edges; } const SubRoom * GraphVertex::GetSubRoom() const { - return sub_room; + return sub_room; } bool GraphVertex::HasExit() const { - for(EdgesContainer::const_iterator it = out_edges.begin(); it != out_edges.end(); ++it) - { - if((*it)->IsExit()) return true; - } - return false; + for(EdgesContainer::const_iterator it = out_edges.begin(); it != out_edges.end(); ++it) { + if((*it)->IsExit()) return true; + } + return false; } /** @@ -112,145 +111,145 @@ bool GraphVertex::HasExit() const */ std::pair<const GraphEdge *, double> GraphVertex::GetCheapestDestinationByEdges(const Point & position) const { - std::set<const GraphEdge *> visited; - // map with GrapEdges and their predecessors and distances - std::map<const GraphEdge *, std::pair<const GraphEdge *, double>> destinations; - // priority queue with discovered Edges and their distance. - std::priority_queue< - std::pair<double, const GraphEdge *>, - vector<std::pair<double, const GraphEdge *>>, - std::greater<std::pair<double, const GraphEdge *>> - > queue; - const GraphEdge * exit_edge = NULL; - - - // add all out edges from this vertex to priority queue and destinations. - for(EdgesContainer::const_iterator it = this->GetAllOutEdges()->begin(); it != this->GetAllOutEdges()->end(); ++it) { - double new_distance = (*it)->GetWeight(position); - - destinations[(*it)] = std::make_pair((const GraphEdge*) NULL, new_distance); - queue.push(std::make_pair(new_distance, (*it))); - } - - while(!queue.empty()) { - const GraphEdge * act_edge = queue.top().second; - double act_distance = queue.top().first; - queue.pop(); - - //if we discovered an exit edge we are finished (queue is distance ordered) - if(act_edge->IsExit()) { - exit_edge = act_edge; - break; - } - - //discover new edges or shorter paths to old edges - const EdgesContainer * new_edges = act_edge->GetDest()->GetAllOutEdges(); - - for(EdgesContainer::const_iterator it = new_edges->begin(); it != new_edges->end(); ++it) { - // if the destination edges was visited we already have the shortest path to this destination. - if(visited.find((*it)) != visited.end()) continue; - - double new_distance = act_distance + (*it)->GetWeight(act_edge->GetCrossing()->GetCentre()); - //check if the destination edge was discovered before. - if(destinations.find((*it)) == destinations.end()) { - //initialize the new discovered vertex with distance inifity and push it to the queue - destinations[(*it)] = std::make_pair<const GraphEdge*, double>(NULL, INFINITY); - queue.push(std::make_pair(new_distance, (*it))); - } - //check if we found a shorter path to the dest vertex - if(destinations[(*it)].second > new_distance) { - destinations[(*it)].second = new_distance; - destinations[(*it)].first = act_edge; - } - } - visited.insert(act_edge); - } - //did we found an exits? - if(exit_edge != NULL) { - const GraphEdge * act_edge = destinations[exit_edge].first; - if(act_edge == NULL) { - return std::make_pair(exit_edge, destinations[exit_edge].second); - } else { - while(this != act_edge->GetSrc()) { - act_edge = destinations[act_edge].first; - } - return std::make_pair(act_edge, destinations[exit_edge].second); - } - } else { - return std::make_pair<const GraphEdge*, double>(NULL, INFINITY); - } + std::set<const GraphEdge *> visited; + // map with GrapEdges and their predecessors and distances + std::map<const GraphEdge *, std::pair<const GraphEdge *, double>> destinations; + // priority queue with discovered Edges and their distance. + std::priority_queue< + std::pair<double, const GraphEdge *>, + vector<std::pair<double, const GraphEdge *>>, + std::greater<std::pair<double, const GraphEdge *>> + > queue; + const GraphEdge * exit_edge = NULL; + + + // add all out edges from this vertex to priority queue and destinations. + for(EdgesContainer::const_iterator it = this->GetAllOutEdges()->begin(); it != this->GetAllOutEdges()->end(); ++it) { + double new_distance = (*it)->GetWeight(position); + + destinations[(*it)] = std::make_pair((const GraphEdge*) NULL, new_distance); + queue.push(std::make_pair(new_distance, (*it))); + } + + while(!queue.empty()) { + const GraphEdge * act_edge = queue.top().second; + double act_distance = queue.top().first; + queue.pop(); + + //if we discovered an exit edge we are finished (queue is distance ordered) + if(act_edge->IsExit()) { + exit_edge = act_edge; + break; + } + + //discover new edges or shorter paths to old edges + const EdgesContainer * new_edges = act_edge->GetDest()->GetAllOutEdges(); + + for(EdgesContainer::const_iterator it = new_edges->begin(); it != new_edges->end(); ++it) { + // if the destination edges was visited we already have the shortest path to this destination. + if(visited.find((*it)) != visited.end()) continue; + + double new_distance = act_distance + (*it)->GetWeight(act_edge->GetCrossing()->GetCentre()); + //check if the destination edge was discovered before. + if(destinations.find((*it)) == destinations.end()) { + //initialize the new discovered vertex with distance inifity and push it to the queue + destinations[(*it)] = std::make_pair<const GraphEdge*, double>(NULL, INFINITY); + queue.push(std::make_pair(new_distance, (*it))); + } + //check if we found a shorter path to the dest vertex + if(destinations[(*it)].second > new_distance) { + destinations[(*it)].second = new_distance; + destinations[(*it)].first = act_edge; + } + } + visited.insert(act_edge); + } + //did we found an exits? + if(exit_edge != NULL) { + const GraphEdge * act_edge = destinations[exit_edge].first; + if(act_edge == NULL) { + return std::make_pair(exit_edge, destinations[exit_edge].second); + } else { + while(this != act_edge->GetSrc()) { + act_edge = destinations[act_edge].first; + } + return std::make_pair(act_edge, destinations[exit_edge].second); + } + } else { + return std::make_pair<const GraphEdge*, double>(NULL, INFINITY); + } } std::pair<const GraphEdge *, double> GraphVertex::GetCheapestDestination(const Point & position) const { - std::set<const GraphVertex *> visited; - std::map<const GraphVertex *, std::pair<const GraphEdge *, double>> destinations; - std::priority_queue<std::pair<double, const GraphVertex *>, vector<std::pair<double, const GraphVertex *>>, std::greater<std::pair<double, const GraphVertex *>>> queue; - - destinations[this] = std::make_pair<const GraphEdge *, double>(NULL, 0.0); - - - //first edges should be handled separated to recalculate edge weight - for(EdgesContainer::const_iterator it = this->GetAllOutEdges()->begin(); it != this->GetAllOutEdges()->end(); ++it) { - double new_distance = (*it)->GetWeight(position); - //check if the destination vertex was discovered before. - if(destinations.find((*it)->GetDest()) == destinations.end()) { - //initialize the new discovered vertex with distance inifity and push it to the queue - destinations[(*it)->GetDest()] = std::make_pair<const GraphEdge*, double>(NULL, INFINITY); - queue.push(std::make_pair(new_distance, (*it)->GetDest())); - } - - //check if we found a shorter path to the dest vertex - if(destinations[(*it)->GetDest()].second > new_distance) { - destinations[(*it)->GetDest()].second = new_distance; - destinations[(*it)->GetDest()].first = (*it); - } - } - visited.insert(this); - - while(!queue.empty()) { - const GraphVertex * act_vertex = queue.top().second; - double act_distance = queue.top().first; - queue.pop(); - const EdgesContainer * act_edges = act_vertex->GetAllOutEdges(); - - // NULL Pointer is used for exit node - // this only works if the priority queue is sorted with lowest weight. - // so if we have null pointer as act. vertex there is no shorter path to the exit - if(act_vertex == NULL) { - break; - } - - for(EdgesContainer::const_iterator it = act_edges->begin(); it != act_edges->end(); ++it) { - // if the dest vertex was visited we already have the shortest path to this dest. - if(visited.find((*it)->GetDest()) != visited.end()) continue; - - double new_distance = act_distance + (*it)->GetWeight((*it)->GetSrc()->GetSubRoom()->GetCentroid()); - //check if the destination vertex was discovered before. - if(destinations.find((*it)->GetDest()) == destinations.end()) { - //initialize the new discovered vertex with distance inifity and push it to the queue - destinations[(*it)->GetDest()] = std::make_pair<const GraphEdge*, double>(NULL, INFINITY); - queue.push(std::make_pair(new_distance, (*it)->GetDest())); - } - - //check if we found a shorter path to the dest vertex - if(destinations[(*it)->GetDest()].second > new_distance) { - destinations[(*it)->GetDest()].second = new_distance; - destinations[(*it)->GetDest()].first = (*it); - } - } - visited.insert(act_vertex); - } - //NULL Pointer is outside the building, so the edge is the Exit - if(destinations.find(NULL) != destinations.end()) { - const GraphEdge * act_edge = destinations[NULL].first; - while(this != act_edge->GetSrc()) { - act_edge = destinations[act_edge->GetSrc()].first; - } - return std::make_pair(act_edge, destinations[NULL].second); - } else { - return std::make_pair<const GraphEdge*, double>(NULL, INFINITY); - } + std::set<const GraphVertex *> visited; + std::map<const GraphVertex *, std::pair<const GraphEdge *, double>> destinations; + std::priority_queue<std::pair<double, const GraphVertex *>, vector<std::pair<double, const GraphVertex *>>, std::greater<std::pair<double, const GraphVertex *>>> queue; + + destinations[this] = std::make_pair<const GraphEdge *, double>(NULL, 0.0); + + + //first edges should be handled separated to recalculate edge weight + for(EdgesContainer::const_iterator it = this->GetAllOutEdges()->begin(); it != this->GetAllOutEdges()->end(); ++it) { + double new_distance = (*it)->GetWeight(position); + //check if the destination vertex was discovered before. + if(destinations.find((*it)->GetDest()) == destinations.end()) { + //initialize the new discovered vertex with distance inifity and push it to the queue + destinations[(*it)->GetDest()] = std::make_pair<const GraphEdge*, double>(NULL, INFINITY); + queue.push(std::make_pair(new_distance, (*it)->GetDest())); + } + + //check if we found a shorter path to the dest vertex + if(destinations[(*it)->GetDest()].second > new_distance) { + destinations[(*it)->GetDest()].second = new_distance; + destinations[(*it)->GetDest()].first = (*it); + } + } + visited.insert(this); + + while(!queue.empty()) { + const GraphVertex * act_vertex = queue.top().second; + double act_distance = queue.top().first; + queue.pop(); + const EdgesContainer * act_edges = act_vertex->GetAllOutEdges(); + + // NULL Pointer is used for exit node + // this only works if the priority queue is sorted with lowest weight. + // so if we have null pointer as act. vertex there is no shorter path to the exit + if(act_vertex == NULL) { + break; + } + + for(EdgesContainer::const_iterator it = act_edges->begin(); it != act_edges->end(); ++it) { + // if the dest vertex was visited we already have the shortest path to this dest. + if(visited.find((*it)->GetDest()) != visited.end()) continue; + + double new_distance = act_distance + (*it)->GetWeight((*it)->GetSrc()->GetSubRoom()->GetCentroid()); + //check if the destination vertex was discovered before. + if(destinations.find((*it)->GetDest()) == destinations.end()) { + //initialize the new discovered vertex with distance inifity and push it to the queue + destinations[(*it)->GetDest()] = std::make_pair<const GraphEdge*, double>(NULL, INFINITY); + queue.push(std::make_pair(new_distance, (*it)->GetDest())); + } + + //check if we found a shorter path to the dest vertex + if(destinations[(*it)->GetDest()].second > new_distance) { + destinations[(*it)->GetDest()].second = new_distance; + destinations[(*it)->GetDest()].first = (*it); + } + } + visited.insert(act_vertex); + } + //NULL Pointer is outside the building, so the edge is the Exit + if(destinations.find(NULL) != destinations.end()) { + const GraphEdge * act_edge = destinations[NULL].first; + while(this != act_edge->GetSrc()) { + act_edge = destinations[act_edge->GetSrc()].first; + } + return std::make_pair(act_edge, destinations[NULL].second); + } else { + return std::make_pair<const GraphEdge*, double>(NULL, INFINITY); + } } diff --git a/routing/cognitive_map/navigation_graph/GraphVertex.h b/routing/cognitive_map/navigation_graph/GraphVertex.h index 41ef576bbdd887987e9d4b084461ef61abe499a7..bdfac61cbbb9d2a13cfe74937c27f2ac493a122d 100644 --- a/routing/cognitive_map/navigation_graph/GraphVertex.h +++ b/routing/cognitive_map/navigation_graph/GraphVertex.h @@ -28,41 +28,41 @@ class GraphEdge; */ class GraphVertex { - public: - typedef std::set<GraphEdge *> EdgesContainer; - /**************************** - * Constructors & Destructors - ****************************/ +public: + typedef std::set<GraphEdge *> EdgesContainer; + /**************************** + * Constructors & Destructors + ****************************/ - GraphVertex(const SubRoom * const sub_room); - GraphVertex(GraphVertex const & gv); + GraphVertex(const SubRoom * const sub_room); + GraphVertex(GraphVertex const & gv); - virtual ~GraphVertex(); + virtual ~GraphVertex(); - const std::string GetCaption() const; - const SubRoom * GetSubRoom() const; + const std::string GetCaption() const; + const SubRoom * GetSubRoom() const; - // add and remove edge pointer from vertex + // add and remove edge pointer from vertex - void AddOutEdge(const GraphVertex * const dest, const Crossing * const crossing); - int RemoveOutEdge(const GraphVertex * dest); - int RemoveOutEdge(GraphEdge * edge); - const EdgesContainer * GetAllOutEdges() const; - EdgesContainer * GetAllEdges(); + void AddOutEdge(const GraphVertex * const dest, const Crossing * const crossing); + int RemoveOutEdge(const GraphVertex * dest); + int RemoveOutEdge(GraphEdge * edge); + const EdgesContainer * GetAllOutEdges() const; + EdgesContainer * GetAllEdges(); - void AddExit(const Transition * transition); - bool HasExit() const; + void AddExit(const Transition * transition); + bool HasExit() const; - std::pair<const GraphEdge *, double> GetCheapestDestination(const Point & position) const; - std::pair<const GraphEdge *, double> GetCheapestDestinationByEdges(const Point & position) const; + std::pair<const GraphEdge *, double> GetCheapestDestination(const Point & position) const; + std::pair<const GraphEdge *, double> GetCheapestDestinationByEdges(const Point & position) const; - private: - // edges wich are "known" from this vertex - EdgesContainer out_edges; - std::set<GraphEdge *> exits; - const SubRoom * const sub_room; +private: + // edges wich are "known" from this vertex + EdgesContainer out_edges; + std::set<GraphEdge *> exits; + const SubRoom * const sub_room; }; diff --git a/routing/cognitive_map/sensor/AbstractSensor.h b/routing/cognitive_map/sensor/AbstractSensor.h index 4f54aa2633af29475b0d51cc6874fd077f6b75ea..9974f91bc8ea70bc5f8734d99398397869b0bfde 100644 --- a/routing/cognitive_map/sensor/AbstractSensor.h +++ b/routing/cognitive_map/sensor/AbstractSensor.h @@ -16,16 +16,15 @@ class CognitiveMap; -class AbstractSensor -{ - public: - AbstractSensor(const Building * b) : building(b) {} - virtual ~AbstractSensor(); - - virtual std::string GetName() const = 0; - virtual void execute(const Pedestrian *, CognitiveMap *) const = 0; - protected: - const Building * const building; +class AbstractSensor { +public: + AbstractSensor(const Building * b) : building(b) {} + virtual ~AbstractSensor(); + + virtual std::string GetName() const = 0; + virtual void execute(const Pedestrian *, CognitiveMap *) const = 0; +protected: + const Building * const building; }; #endif // ABSTRACTSENSOR_H diff --git a/routing/cognitive_map/sensor/RoomToFloorSensor.cpp b/routing/cognitive_map/sensor/RoomToFloorSensor.cpp index 6d6dc0368e535a746f0596af9c8d1b56fc00ad04..53c4ff95fe00f49cd355811940ef0dd009124237 100644 --- a/routing/cognitive_map/sensor/RoomToFloorSensor.cpp +++ b/routing/cognitive_map/sensor/RoomToFloorSensor.cpp @@ -16,26 +16,26 @@ RoomToFloorSensor::~RoomToFloorSensor() std::string RoomToFloorSensor::GetName() const { - return "RoomToFloorSensor"; + return "RoomToFloorSensor"; } void RoomToFloorSensor::execute(const Pedestrian * pedestrian, CognitiveMap * cognitive_map) const { - NavigationGraph::VerticesContainer * vertices = cognitive_map->GetAllVertices(); + NavigationGraph::VerticesContainer * vertices = cognitive_map->GetAllVertices(); - //iterating over all Vertices - for(NavigationGraph::VerticesContainer::iterator it_vertices = vertices->begin(); it_vertices != vertices->end(); ++it_vertices) { - GraphVertex::EdgesContainer * edges = (it_vertices->second)->GetAllEdges(); - //iterating over all edges - for(GraphVertex::EdgesContainer::iterator it_edges = edges->begin(); it_edges != edges->end(); ++it_edges) { - if((*it_edges)->GetDest() == NULL || (*it_edges)->GetDest()->GetSubRoom()->GetType() == (*it_edges)->GetSrc()->GetSubRoom()->GetType()) { - (*it_edges)->SetFactor(1.0, GetName()); - } else { - if((*it_edges)->GetDest()->GetSubRoom()->GetType() == "floor") - (*it_edges)->SetFactor(1.0 , GetName()); - else - (*it_edges)->SetFactor(3.0 , GetName()); - } - } - } + //iterating over all Vertices + for(NavigationGraph::VerticesContainer::iterator it_vertices = vertices->begin(); it_vertices != vertices->end(); ++it_vertices) { + GraphVertex::EdgesContainer * edges = (it_vertices->second)->GetAllEdges(); + //iterating over all edges + for(GraphVertex::EdgesContainer::iterator it_edges = edges->begin(); it_edges != edges->end(); ++it_edges) { + if((*it_edges)->GetDest() == NULL || (*it_edges)->GetDest()->GetSubRoom()->GetType() == (*it_edges)->GetSrc()->GetSubRoom()->GetType()) { + (*it_edges)->SetFactor(1.0, GetName()); + } else { + if((*it_edges)->GetDest()->GetSubRoom()->GetType() == "floor") + (*it_edges)->SetFactor(1.0 , GetName()); + else + (*it_edges)->SetFactor(3.0 , GetName()); + } + } + } } diff --git a/routing/cognitive_map/sensor/RoomToFloorSensor.h b/routing/cognitive_map/sensor/RoomToFloorSensor.h index 8b38d4a0723e7f9984e38468d66492943ae4c326..f386d95fe105c7645cda443940636d524638c4e9 100644 --- a/routing/cognitive_map/sensor/RoomToFloorSensor.h +++ b/routing/cognitive_map/sensor/RoomToFloorSensor.h @@ -12,17 +12,16 @@ #include "AbstractSensor.h" -class RoomToFloorSensor : public AbstractSensor -{ +class RoomToFloorSensor : public AbstractSensor { - public: - RoomToFloorSensor(const Building * b) : AbstractSensor(b) { } +public: + RoomToFloorSensor(const Building * b) : AbstractSensor(b) { } - virtual ~RoomToFloorSensor(); + virtual ~RoomToFloorSensor(); - std::string GetName() const; - void execute(const Pedestrian *, CognitiveMap *) const; - private: + std::string GetName() const; + void execute(const Pedestrian *, CognitiveMap *) const; +private: }; diff --git a/routing/cognitive_map/sensor/SensorManager.cpp b/routing/cognitive_map/sensor/SensorManager.cpp index 9ef5ca482dc5a8f68437b70a8ae7c75f157a9010..d6dbed8bd9f9b91c6daa709e723ee160dba8d92d 100644 --- a/routing/cognitive_map/sensor/SensorManager.cpp +++ b/routing/cognitive_map/sensor/SensorManager.cpp @@ -15,7 +15,7 @@ #include "../CognitiveMap.h" SensorManager::SensorManager(const Building * b, CognitiveMapStorage * cms) - : building(b), cm_storage(cms) + : building(b), cm_storage(cms) { } @@ -26,24 +26,24 @@ SensorManager::~SensorManager() void SensorManager::execute(const Pedestrian * ped, EventType event_type) { - for(SensorContainer::iterator it = registered_sensors.begin(); it != registered_sensors.end(); ++it) { - if(event_type & it->second) { - it->first->execute(ped, (*cm_storage)[ped]); - } - } + for(SensorContainer::iterator it = registered_sensors.begin(); it != registered_sensors.end(); ++it) { + if(event_type & it->second) { + it->first->execute(ped, (*cm_storage)[ped]); + } + } } void SensorManager::Register(AbstractSensor * sensor, EventType events) { - registered_sensors.push_back(std::make_pair(sensor, events)); + registered_sensors.push_back(std::make_pair(sensor, events)); } SensorManager * SensorManager::InitWithAllSensors(const Building * b, CognitiveMapStorage * cm_storage) { - SensorManager * sensor_manager = new SensorManager(b, cm_storage); + SensorManager * sensor_manager = new SensorManager(b, cm_storage); - //Init and register Sensors - sensor_manager->Register(new RoomToFloorSensor(b), INIT | PERIODIC | NO_WAY ); + //Init and register Sensors + sensor_manager->Register(new RoomToFloorSensor(b), INIT | PERIODIC | NO_WAY ); - return sensor_manager; + return sensor_manager; } diff --git a/routing/cognitive_map/sensor/SensorManager.h b/routing/cognitive_map/sensor/SensorManager.h index b2e7b3b857500b665dff801bdee5c8c04170f062..8b11675f2a99b383eea223f6aaf086e3f18073a4 100644 --- a/routing/cognitive_map/sensor/SensorManager.h +++ b/routing/cognitive_map/sensor/SensorManager.h @@ -19,32 +19,32 @@ class Pedestrian; #include <set> class SensorManager { - public: - typedef int EventType; - static const EventType NONE = 0; - static const EventType INIT = 1; - static const EventType PERIODIC = 2; - static const EventType NO_WAY = 4; +public: + typedef int EventType; + static const EventType NONE = 0; + static const EventType INIT = 1; + static const EventType PERIODIC = 2; + static const EventType NO_WAY = 4; - typedef std::vector<std::pair<AbstractSensor *, EventType>> SensorContainer; + typedef std::vector<std::pair<AbstractSensor *, EventType>> SensorContainer; - /**************************** - * Constructors & Destructors - ****************************/ - SensorManager(const Building * building, CognitiveMapStorage *); - virtual ~SensorManager(); + /**************************** + * Constructors & Destructors + ****************************/ + SensorManager(const Building * building, CognitiveMapStorage *); + virtual ~SensorManager(); - void Register(AbstractSensor *, EventType); - void execute(const Pedestrian *, EventType); + void Register(AbstractSensor *, EventType); + void execute(const Pedestrian *, EventType); - static SensorManager * InitWithAllSensors(const Building *, CognitiveMapStorage *); + static SensorManager * InitWithAllSensors(const Building *, CognitiveMapStorage *); - private: - const Building * const building; - CognitiveMapStorage * cm_storage; +private: + const Building * const building; + CognitiveMapStorage * cm_storage; - SensorContainer registered_sensors; + SensorContainer registered_sensors; }; diff --git a/routing/graph/NavLineState.cpp b/routing/graph/NavLineState.cpp index 6ee541736254bbb4cc046387be5f0e87c11755c5..20a72b268d264efb6c5c10bc8a449426189a010b 100644 --- a/routing/graph/NavLineState.cpp +++ b/routing/graph/NavLineState.cpp @@ -10,53 +10,55 @@ -NavLineState::NavLineState() +NavLineState::NavLineState() { - open = true; - timeOfInformation = 0; - timeFirstSeen = 0; + open = true; + timeOfInformation = 0; + timeFirstSeen = 0; } NavLineState::~NavLineState() { - + } -void NavLineState::close(double time){ - open = false; - timeOfInformation = time; - timeFirstSeen = time; +void NavLineState::close(double time) +{ + open = false; + timeOfInformation = time; + timeFirstSeen = time; } -bool NavLineState::closed() +bool NavLineState::closed() { - return !open; - + return !open; + } -bool NavLineState::isShareable(double time) +bool NavLineState::isShareable(double time) { - if(!timeOfInformation) return true; - if(timeOfInformation+INFO_OFFSET < time) { - timeOfInformation = 0; - return true; - } - return false; - - + if(!timeOfInformation) return true; + if(timeOfInformation+INFO_OFFSET < time) { + timeOfInformation = 0; + return true; + } + return false; + + } bool NavLineState::mergeDoor(NavLineState & orig, double time) { - if(timeFirstSeen == 0 || orig.timeFirstSeen > timeFirstSeen) { - open = orig.open; - timeFirstSeen = orig.timeFirstSeen; - timeOfInformation = time; - return true; - } - return false; + if(timeFirstSeen == 0 || orig.timeFirstSeen > timeFirstSeen) { + open = orig.open; + timeFirstSeen = orig.timeFirstSeen; + timeOfInformation = time; + return true; + } + return false; } -void NavLineState::print() { - std::cout << open << " - "<< timeFirstSeen << " - " << timeOfInformation << std::endl; +void NavLineState::print() +{ + std::cout << open << " - "<< timeFirstSeen << " - " << timeOfInformation << std::endl; } diff --git a/routing/graph/NavLineState.h b/routing/graph/NavLineState.h index fb88612b47095f7fc4c72be495eb29d10530bc9d..23f5254d3b57ceaaed6c5932dda643300f84c2c4 100644 --- a/routing/graph/NavLineState.h +++ b/routing/graph/NavLineState.h @@ -15,24 +15,23 @@ //time between a pedestrian got the information and uses the information #define INFO_OFFSET 1.5 -class NavLineState -{ - - public: - NavLineState(); - ~NavLineState(); - - bool closed(); - bool isShareable(double time); - void close(double time); - bool mergeDoor(NavLineState & orig, double time); - void print(); - - private: - bool open; // aka state - int timeFirstSeen; // number of clocks till the door was seen changed the first time - int timeOfInformation; // number of clocks when i got the information. should be set to zero after a period of time is over (to - +class NavLineState { + +public: + NavLineState(); + ~NavLineState(); + + bool closed(); + bool isShareable(double time); + void close(double time); + bool mergeDoor(NavLineState & orig, double time); + void print(); + +private: + bool open; // aka state + int timeFirstSeen; // number of clocks till the door was seen changed the first time + int timeOfInformation; // number of clocks when i got the information. should be set to zero after a period of time is over (to + }; #endif /* ROUTINGGRAPHSTORAGE_H_ */ diff --git a/routing/graph/RoutingGraph.cpp b/routing/graph/RoutingGraph.cpp index 30bb799c127478e11bda41a547ac505a7651bb69..396e946ab7cada432715a03ec62fa0dbddf5de0f 100644 --- a/routing/graph/RoutingGraph.cpp +++ b/routing/graph/RoutingGraph.cpp @@ -23,15 +23,15 @@ using namespace std; */ RoutingGraph::RoutingGraph(Building * b) : building(b) { - vertexes = map<int, Vertex>(); + vertexes = map<int, Vertex>(); - BuildGraph(); + BuildGraph(); }; RoutingGraph::RoutingGraph() { - vertexes = map<int, Vertex>(); + vertexes = map<int, Vertex>(); } RoutingGraph::~RoutingGraph() @@ -41,28 +41,28 @@ RoutingGraph::~RoutingGraph() RoutingGraph::RoutingGraph(RoutingGraph * orig) { - building = orig->building; - vertexes = orig->vertexes; + building = orig->building; + vertexes = orig->vertexes; - map<int, Vertex>::iterator itv; - map<int, Edge>::iterator ite; - map<int, ExitDistance>::iterator ited; + map<int, Vertex>::iterator itv; + map<int, Edge>::iterator ite; + map<int, ExitDistance>::iterator ited; - for(itv = orig->vertexes.begin(); itv != orig->vertexes.end(); itv++) { - // set the right edge->src and edge->dest pointers - for(ite = itv->second.edges.begin(); ite != itv->second.edges.end(); ite++) { - vertexes[itv->first].edges[ite->first].src = &vertexes[itv->first]; - vertexes[itv->first].edges[ite->first].dest = &vertexes[ite->second.dest->id]; - } + for(itv = orig->vertexes.begin(); itv != orig->vertexes.end(); itv++) { + // set the right edge->src and edge->dest pointers + for(ite = itv->second.edges.begin(); ite != itv->second.edges.end(); ite++) { + vertexes[itv->first].edges[ite->first].src = &vertexes[itv->first]; + vertexes[itv->first].edges[ite->first].dest = &vertexes[ite->second.dest->id]; + } - // set the right ExitDistance->edge pointer - for(ited = itv->second.distances.begin(); ited != itv->second.distances.end(); ited++){ - if(ited->second.exit_edge) - vertexes[itv->first].distances[ited->first].exit_edge = &vertexes[itv->first].edges[ited->second.exit_edge->dest->id]; + // set the right ExitDistance->edge pointer + for(ited = itv->second.distances.begin(); ited != itv->second.distances.end(); ited++) { + if(ited->second.exit_edge) + vertexes[itv->first].distances[ited->first].exit_edge = &vertexes[itv->first].edges[ited->second.exit_edge->dest->id]; - } + } - } + } } @@ -75,8 +75,8 @@ RoutingGraph::RoutingGraph(RoutingGraph * orig) */ ExitDistance RoutingGraph::GetNextDestination(int nav_line_index, Pedestrian * p) { - ExitDistance dist = vertexes[nav_line_index].getShortestExit(); - return dist; + ExitDistance dist = vertexes[nav_line_index].getShortestExit(); + return dist; } @@ -87,65 +87,65 @@ ExitDistance RoutingGraph::GetNextDestination(int nav_line_index, Pedestrian * p */ ExitDistance RoutingGraph::GetNextDestination(Pedestrian * p) { - double act_shortest_dist = INFINITY; - NavLine * return_line = NULL; - SubRoom * sub = building->GetRoom(p->GetRoomID())->GetSubRoom(p->GetSubRoomID()); - ExitDistance ed; - - //collecting all lines to check - vector<NavLine*> lines; - lines.insert(lines.end(), sub->GetAllCrossings().begin(), sub->GetAllCrossings().end()); - lines.insert(lines.end(), sub->GetAllTransitions().begin(), sub->GetAllTransitions().end()); - lines.insert(lines.end(), sub->GetAllHlines().begin(), sub->GetAllHlines().end()); - - for(unsigned int i = 0; i < lines.size(); i++) { - // check if the exit exists in the routing graph and the line is visible for the pedestrian - if(GetVertex(lines[i]->GetUniqueID()) && checkVisibility(p, lines[i], sub )) { - ed = GetVertex(lines[i]->GetUniqueID())->getShortestExit(); - Hline * hline = dynamic_cast<Hline*>(lines[i]); - //check if it is a hline OR it is an exit OR the exit is not thorugh the same subroom - if(hline || GetVertex(lines[i]->GetUniqueID())->exit || p->GetRoomID() != ed.GetSubRoom()->GetRoomID() || p->GetSubRoomID() != ed.GetSubRoom()->GetSubRoomID()) { - // check if the distance is shorter - double distance = (lines[i]->GetCentre()-p->GetPos()).Norm() + ed.distance; - if(act_shortest_dist > distance ) { - act_shortest_dist = distance; - return_line = lines[i]; - } - } - } - - } - ExitDistance return_dist; - - if(!return_line) { - char tmp[CLENGTH]; - sprintf(tmp, - "ERROR: \t Pedestrian [%d] can't find a exit.at X=%f Y = %f Removed Pedestrian.", - p->GetID(), p->GetPos().GetX(), p->GetPos().GetY()); - Log->Write(tmp); - return return_dist; - } - - ed = GetVertex(return_line->GetUniqueID())->getShortestExit(); - - return_dist.distance = act_shortest_dist; - // - return_dist.exit_edge = NULL; - - if(ed.exit_vertex->id != return_line->GetUniqueID()){ - return_dist.exit_edge = new Edge(); - return_dist.exit_edge->dest = GetVertex(return_line->GetUniqueID()); - return_dist.exit_edge->sub = sub; - return_dist.exit_edge->src = NULL; - - } - - - return_dist.exit_vertex = ed.exit_vertex; - - - - return return_dist; + double act_shortest_dist = INFINITY; + NavLine * return_line = NULL; + SubRoom * sub = building->GetRoom(p->GetRoomID())->GetSubRoom(p->GetSubRoomID()); + ExitDistance ed; + + //collecting all lines to check + vector<NavLine*> lines; + lines.insert(lines.end(), sub->GetAllCrossings().begin(), sub->GetAllCrossings().end()); + lines.insert(lines.end(), sub->GetAllTransitions().begin(), sub->GetAllTransitions().end()); + lines.insert(lines.end(), sub->GetAllHlines().begin(), sub->GetAllHlines().end()); + + for(unsigned int i = 0; i < lines.size(); i++) { + // check if the exit exists in the routing graph and the line is visible for the pedestrian + if(GetVertex(lines[i]->GetUniqueID()) && checkVisibility(p, lines[i], sub )) { + ed = GetVertex(lines[i]->GetUniqueID())->getShortestExit(); + Hline * hline = dynamic_cast<Hline*>(lines[i]); + //check if it is a hline OR it is an exit OR the exit is not thorugh the same subroom + if(hline || GetVertex(lines[i]->GetUniqueID())->exit || p->GetRoomID() != ed.GetSubRoom()->GetRoomID() || p->GetSubRoomID() != ed.GetSubRoom()->GetSubRoomID()) { + // check if the distance is shorter + double distance = (lines[i]->GetCentre()-p->GetPos()).Norm() + ed.distance; + if(act_shortest_dist > distance ) { + act_shortest_dist = distance; + return_line = lines[i]; + } + } + } + + } + ExitDistance return_dist; + + if(!return_line) { + char tmp[CLENGTH]; + sprintf(tmp, + "ERROR: \t Pedestrian [%d] can't find a exit.at X=%f Y = %f Removed Pedestrian.", + p->GetID(), p->GetPos().GetX(), p->GetPos().GetY()); + Log->Write(tmp); + return return_dist; + } + + ed = GetVertex(return_line->GetUniqueID())->getShortestExit(); + + return_dist.distance = act_shortest_dist; + // + return_dist.exit_edge = NULL; + + if(ed.exit_vertex->id != return_line->GetUniqueID()) { + return_dist.exit_edge = new Edge(); + return_dist.exit_edge->dest = GetVertex(return_line->GetUniqueID()); + return_dist.exit_edge->sub = sub; + return_dist.exit_edge->src = NULL; + + } + + + return_dist.exit_vertex = ed.exit_vertex; + + + + return return_dist; } @@ -156,26 +156,26 @@ ExitDistance RoutingGraph::GetNextDestination(Pedestrian * p) RoutingGraph * RoutingGraph::BuildGraph() { - // Get all Rooms from the building object - const vector<Room*> * rooms = & building->GetAllRooms(); - for(unsigned int i = 0; i < rooms->size(); i++) { - // go through all subroom and retrieve all nav lines - const vector<SubRoom*> * subrooms = & (*rooms)[i]->GetAllSubRooms(); - for(unsigned int k = 0; k < subrooms->size(); k++) { - processSubroom((*subrooms)[k]); - } - } - - map<int, Vertex>::iterator it; - //calculate the distances for Exits! - for(it = vertexes.begin(); it != vertexes.end(); it++) { - - if(it->second.exit) { - calculateDistancesForExit(&it->second); - } - } - //print(); - return this; + // Get all Rooms from the building object + const vector<Room*> * rooms = & building->GetAllRooms(); + for(unsigned int i = 0; i < rooms->size(); i++) { + // go through all subroom and retrieve all nav lines + const vector<SubRoom*> * subrooms = & (*rooms)[i]->GetAllSubRooms(); + for(unsigned int k = 0; k < subrooms->size(); k++) { + processSubroom((*subrooms)[k]); + } + } + + map<int, Vertex>::iterator it; + //calculate the distances for Exits! + for(it = vertexes.begin(); it != vertexes.end(); it++) { + + if(it->second.exit) { + calculateDistancesForExit(&it->second); + } + } + //print(); + return this; }; /** @@ -186,43 +186,43 @@ RoutingGraph * RoutingGraph::BuildGraph() int RoutingGraph::addVertex(NavLine * nav_line, bool exit) { - if(!nav_line) return -1; - int id = nav_line->GetUniqueID(); - vertexes[id].nav_line = nav_line; - vertexes[id].id = id; - vertexes[id].exit = exit; - return id; + if(!nav_line) return -1; + int id = nav_line->GetUniqueID(); + vertexes[id].nav_line = nav_line; + vertexes[id].id = id; + vertexes[id].exit = exit; + return id; } void RoutingGraph::removeVertex(Vertex * remove_vertex) { - if(!remove_vertex) - return; + if(!remove_vertex) + return; - // remove all edges - map<int, Edge>::iterator it_e; + // remove all edges + map<int, Edge>::iterator it_e; - for(it_e = remove_vertex->edges.begin(); it_e != remove_vertex->edges.end(); it_e++) { - it_e->second.dest->edges.erase(remove_vertex->id); - } + for(it_e = remove_vertex->edges.begin(); it_e != remove_vertex->edges.end(); it_e++) { + it_e->second.dest->edges.erase(remove_vertex->id); + } - // remove vertex - vertexes.erase(remove_vertex->id); + // remove vertex + vertexes.erase(remove_vertex->id); - // calculate new distance, maybe some distance changed because the door is closed. - map<int, Vertex>::iterator it; - //calculate the distances for Exits! - for(it = vertexes.begin(); it != vertexes.end(); it++) { + // calculate new distance, maybe some distance changed because the door is closed. + map<int, Vertex>::iterator it; + //calculate the distances for Exits! + for(it = vertexes.begin(); it != vertexes.end(); it++) { - it->second.distances.clear(); - } + it->second.distances.clear(); + } - for(it = vertexes.begin(); it != vertexes.end(); it++) { + for(it = vertexes.begin(); it != vertexes.end(); it++) { - if(it->second.exit) { - calculateDistancesForExit(&it->second); - } - } + if(it->second.exit) { + calculateDistancesForExit(&it->second); + } + } @@ -231,8 +231,8 @@ void RoutingGraph::removeVertex(Vertex * remove_vertex) void RoutingGraph::closeDoor(int id) { - removeVertex(GetVertex(id)); - return; + removeVertex(GetVertex(id)); + return; } /** * RoutingGraph::processSubroom @@ -240,31 +240,31 @@ void RoutingGraph::closeDoor(int id) */ void RoutingGraph::processSubroom(SubRoom * sub) { - vector<int> goals; - // add all crossings, transitions, hlines as vertex - // save the insert id to add all edges in a subroom - for(unsigned int i = 0; i < sub->GetAllCrossings().size(); i++) { - goals.push_back(addVertex(sub->GetAllCrossings()[i])); - } - for(unsigned int i = 0; i < sub->GetAllTransitions().size(); i++) { - if(sub->GetAllTransitions()[i]->IsOpen()) - goals.push_back(addVertex(sub->GetAllTransitions()[i], sub->GetAllTransitions()[i]->IsExit())); - } - for(unsigned int i = 0; i < sub->GetAllHlines().size(); i++) { - goals.push_back(addVertex(sub->GetAllHlines()[i])); - - } - - // now add all edges between all goals - // check if they visible by each other - if(goals.size() > 1) { - for(unsigned int k = 0; k < goals.size()-1; k++) { - for(unsigned int i = k+1; i < goals.size(); i++) { - addEdge(GetVertex(goals[k]), GetVertex(goals[i]), sub); - addEdge(GetVertex(goals[i]), GetVertex(goals[k]), sub); - } - } - } + vector<int> goals; + // add all crossings, transitions, hlines as vertex + // save the insert id to add all edges in a subroom + for(unsigned int i = 0; i < sub->GetAllCrossings().size(); i++) { + goals.push_back(addVertex(sub->GetAllCrossings()[i])); + } + for(unsigned int i = 0; i < sub->GetAllTransitions().size(); i++) { + if(sub->GetAllTransitions()[i]->IsOpen()) + goals.push_back(addVertex(sub->GetAllTransitions()[i], sub->GetAllTransitions()[i]->IsExit())); + } + for(unsigned int i = 0; i < sub->GetAllHlines().size(); i++) { + goals.push_back(addVertex(sub->GetAllHlines()[i])); + + } + + // now add all edges between all goals + // check if they visible by each other + if(goals.size() > 1) { + for(unsigned int k = 0; k < goals.size()-1; k++) { + for(unsigned int i = k+1; i < goals.size(); i++) { + addEdge(GetVertex(goals[k]), GetVertex(goals[i]), sub); + addEdge(GetVertex(goals[i]), GetVertex(goals[k]), sub); + } + } + } } /** @@ -274,36 +274,36 @@ void RoutingGraph::processSubroom(SubRoom * sub) void RoutingGraph::addEdge(Vertex * v1, Vertex * v2, SubRoom* sub) { - Edge new_edge; + Edge new_edge; - // do not add loops! - if(v1->id == v2->id) - return; + // do not add loops! + if(v1->id == v2->id) + return; - //TODO: sometime checkVisibility is not commutative (cV(v1,v2) != cV(v2,v1)) - if(checkVisibility(v1->nav_line, v2->nav_line, sub) || checkVisibility(v2->nav_line, v1->nav_line, sub)) { + //TODO: sometime checkVisibility is not commutative (cV(v1,v2) != cV(v2,v1)) + if(checkVisibility(v1->nav_line, v2->nav_line, sub) || checkVisibility(v2->nav_line, v1->nav_line, sub)) { - new_edge.dest = v2; - new_edge.src = v1; + new_edge.dest = v2; + new_edge.src = v1; - // attention!! this is not the shortest distance. - new_edge.distance = (v1->nav_line->GetCentre() - v2->nav_line->GetCentre()).Norm(); - new_edge.sub = sub; - v1->edges[v2->id] = new_edge; - } + // attention!! this is not the shortest distance. + new_edge.distance = (v1->nav_line->GetCentre() - v2->nav_line->GetCentre()).Norm(); + new_edge.sub = sub; + v1->edges[v2->id] = new_edge; + } }; bool RoutingGraph::checkVisibility(Line* l1, Line* l2, SubRoom* sub) { - return sub->IsVisible(l1,l2,true); + return sub->IsVisible(l1,l2,true); } bool RoutingGraph::checkVisibility(Point& p1, Point& p2, SubRoom* sub) { - return sub->IsVisible(p1,p2,true); + return sub->IsVisible(p1,p2,true); } @@ -311,45 +311,45 @@ bool RoutingGraph::checkVisibility(Point& p1, Point& p2, SubRoom* sub) //checks if a pedestrian is standing in a hline bool RoutingGraph::checkVisibility(Pedestrian * p, NavLine * l, SubRoom* sub) { - // connecting lines to check - const int num_lines = 3; - Line cl[num_lines] = { Line(p->GetPos(), l->GetCentre()), Line(p->GetPos(), l->GetPoint1()), Line(p->GetPos(), l->GetPoint2()) }; - bool temp[num_lines] = { true, true, true }; - - //check for intersection with walls - for(unsigned int i = 0; i < sub->GetAllWalls().size(); i++) { - for(int j = 0; j < num_lines; j++) { - if(temp[j] && cl[j].IntersectionWith(sub->GetAllWalls()[i])) { - temp[j] = false; - } - } - } - //check for intersection with hlines - for(unsigned int i = 0; i < sub->GetAllHlines().size(); i++) { - for(int j = 0; j < num_lines; j++) { - if(temp[j] - && l->GetUniqueID() != sub->GetAllHlines()[i]->GetUniqueID() - && !l->IsInLineSegment(p->GetPos()) - && cl[j].IntersectionWith((*sub->GetAllHlines()[i])) - ) { - temp[j] = false; - } - } - } - - - for(unsigned int i = 0; i < sub->GetAllObstacles().size(); i++) { - Obstacle * obs = sub->GetAllObstacles()[i]; - for(unsigned int k = 0; k<obs->GetAllWalls().size(); k++){ - Wall w = obs->GetAllWalls()[k]; - for(int j = 0; j < num_lines; j++) { - if(temp[j] && cl[j].IntersectionWith(w)) - temp[j] = false; - } - } - } - //at the moment no check for intersection with obstacles - return temp[0] || temp[1] || temp[2]; + // connecting lines to check + const int num_lines = 3; + Line cl[num_lines] = { Line(p->GetPos(), l->GetCentre()), Line(p->GetPos(), l->GetPoint1()), Line(p->GetPos(), l->GetPoint2()) }; + bool temp[num_lines] = { true, true, true }; + + //check for intersection with walls + for(unsigned int i = 0; i < sub->GetAllWalls().size(); i++) { + for(int j = 0; j < num_lines; j++) { + if(temp[j] && cl[j].IntersectionWith(sub->GetAllWalls()[i])) { + temp[j] = false; + } + } + } + //check for intersection with hlines + for(unsigned int i = 0; i < sub->GetAllHlines().size(); i++) { + for(int j = 0; j < num_lines; j++) { + if(temp[j] + && l->GetUniqueID() != sub->GetAllHlines()[i]->GetUniqueID() + && !l->IsInLineSegment(p->GetPos()) + && cl[j].IntersectionWith((*sub->GetAllHlines()[i])) + ) { + temp[j] = false; + } + } + } + + + for(unsigned int i = 0; i < sub->GetAllObstacles().size(); i++) { + Obstacle * obs = sub->GetAllObstacles()[i]; + for(unsigned int k = 0; k<obs->GetAllWalls().size(); k++) { + Wall w = obs->GetAllWalls()[k]; + for(int j = 0; j < num_lines; j++) { + if(temp[j] && cl[j].IntersectionWith(w)) + temp[j] = false; + } + } + } + //at the moment no check for intersection with obstacles + return temp[0] || temp[1] || temp[2]; } @@ -358,19 +358,19 @@ bool RoutingGraph::checkVisibility(Pedestrian * p, NavLine * l, SubRoom* sub) */ void RoutingGraph::calculateDistancesForExit(Vertex *act_vertex) { - if(!act_vertex->exit) return; + if(!act_vertex->exit) return; - act_vertex->distances[act_vertex->id].distance = 0; - act_vertex->distances[act_vertex->id].exit_edge = NULL; - act_vertex->distances[act_vertex->id].exit_vertex = act_vertex; + act_vertex->distances[act_vertex->id].distance = 0; + act_vertex->distances[act_vertex->id].exit_edge = NULL; + act_vertex->distances[act_vertex->id].exit_vertex = act_vertex; - map<int, Edge>::iterator it; + map<int, Edge>::iterator it; - for(it = act_vertex->edges.begin(); it != act_vertex->edges.end(); it++) { - calculateDistances(act_vertex, act_vertex, it->second.dest, it->second.distance); - } + for(it = act_vertex->edges.begin(); it != act_vertex->edges.end(); it++) { + calculateDistances(act_vertex, act_vertex, it->second.dest, it->second.distance); + } } /** * recursive function to calculate distances from one vertex to all others @@ -378,29 +378,29 @@ void RoutingGraph::calculateDistancesForExit(Vertex *act_vertex) */ void RoutingGraph::calculateDistances(Vertex * exit, Vertex * last_vertex, Vertex * act_vertex, double act_distance) { - // Don't change the exit way, if the other route is shorter. - if(act_vertex->distances[exit->id].distance && act_vertex->distances[exit->id].distance < act_distance) { - return; - } - act_vertex->distances[exit->id].distance = act_distance; - act_vertex->distances[exit->id].exit_edge = & act_vertex->edges[last_vertex->id]; - act_vertex->distances[exit->id].exit_vertex = exit; + // Don't change the exit way, if the other route is shorter. + if(act_vertex->distances[exit->id].distance && act_vertex->distances[exit->id].distance < act_distance) { + return; + } + act_vertex->distances[exit->id].distance = act_distance; + act_vertex->distances[exit->id].exit_edge = & act_vertex->edges[last_vertex->id]; + act_vertex->distances[exit->id].exit_vertex = exit; - map<int, Edge>::iterator it; + map<int, Edge>::iterator it; - for(it = act_vertex->edges.begin(); it != act_vertex->edges.end(); it++) { - //if the next vertex is an exit here is nothing to do. - if(!it->second.dest->exit) { + for(it = act_vertex->edges.begin(); it != act_vertex->edges.end(); it++) { + //if the next vertex is an exit here is nothing to do. + if(!it->second.dest->exit) { - // if the edge is through the same room then the exit here is nothing to do, except it is a hline - Hline * hline1 = dynamic_cast<Hline*>(act_vertex->nav_line); - if(hline1 || !(act_vertex->edges[last_vertex->id].sub->GetRoomID() == it->second.sub->GetRoomID() && act_vertex->edges[last_vertex->id].sub->GetSubRoomID() == it->second.sub->GetSubRoomID())) { - calculateDistances(exit, act_vertex, it->second.dest, it->second.distance + act_distance); - } - } - } + // if the edge is through the same room then the exit here is nothing to do, except it is a hline + Hline * hline1 = dynamic_cast<Hline*>(act_vertex->nav_line); + if(hline1 || !(act_vertex->edges[last_vertex->id].sub->GetRoomID() == it->second.sub->GetRoomID() && act_vertex->edges[last_vertex->id].sub->GetSubRoomID() == it->second.sub->GetSubRoomID())) { + calculateDistances(exit, act_vertex, it->second.dest, it->second.distance + act_distance); + } + } + } } /** @@ -408,45 +408,45 @@ void RoutingGraph::calculateDistances(Vertex * exit, Vertex * last_vertex, Verte */ void RoutingGraph::print() { - map<int, Vertex>::iterator it; - map<int, ExitDistance>::iterator it2; - std::cout << vertexes.size() << std::endl; - for(it=vertexes.begin(); it != vertexes.end(); it++ ) { - std::cout << "\n\nvertex: " << (*it).second.nav_line->GetUniqueID() << std::endl; - - Crossing * crossing = dynamic_cast<Crossing*>(it->second.nav_line); - - if(crossing) { - std::cout << " from: " << crossing->GetSubRoom1()->GetRoomID() << "-" << crossing->GetSubRoom1()->GetSubRoomID() << " to:"; - - if(crossing->GetSubRoom2()) - std::cout << crossing->GetSubRoom2()->GetRoomID() << "-" << crossing->GetSubRoom2()->GetSubRoomID() << std::endl; - else - std::cout << "exit" << std::endl; - } else { - std::cout << "hline" << std::endl; - } - std::cout << " edges to "; - map<int, Edge>::iterator it_edges; - - for(it_edges = it->second.edges.begin(); it_edges != (*it).second.edges.end(); it_edges++) { - if(it_edges->second.dest) - std::cout << it_edges->second.dest->nav_line->GetUniqueID() << "(distance " << it_edges->second.distance <<") "; - else - std::cout << "NULL" << "-" ; - } - std::cout << std::endl << std::endl; - std::cout << "exit distances: \n "; - - for(it2 = (*it).second.distances.begin(); it2 != (*it).second.distances.end(); it2++) { - std::cout << (*it2).first << " (" << (*it2).second.distance << ")" ; - if(it2->second.exit_edge) { - std::cout <<"subroom "<< it2->second.GetSubRoom()->GetRoomID() << "-" << (*it2).second.GetSubRoom()->GetSubRoomID() << "next vertex: " << (*it2).second.GetDest()->id <<" \n"; - } else { - std::cout << std::endl; - } - } - } + map<int, Vertex>::iterator it; + map<int, ExitDistance>::iterator it2; + std::cout << vertexes.size() << std::endl; + for(it=vertexes.begin(); it != vertexes.end(); it++ ) { + std::cout << "\n\nvertex: " << (*it).second.nav_line->GetUniqueID() << std::endl; + + Crossing * crossing = dynamic_cast<Crossing*>(it->second.nav_line); + + if(crossing) { + std::cout << " from: " << crossing->GetSubRoom1()->GetRoomID() << "-" << crossing->GetSubRoom1()->GetSubRoomID() << " to:"; + + if(crossing->GetSubRoom2()) + std::cout << crossing->GetSubRoom2()->GetRoomID() << "-" << crossing->GetSubRoom2()->GetSubRoomID() << std::endl; + else + std::cout << "exit" << std::endl; + } else { + std::cout << "hline" << std::endl; + } + std::cout << " edges to "; + map<int, Edge>::iterator it_edges; + + for(it_edges = it->second.edges.begin(); it_edges != (*it).second.edges.end(); it_edges++) { + if(it_edges->second.dest) + std::cout << it_edges->second.dest->nav_line->GetUniqueID() << "(distance " << it_edges->second.distance <<") "; + else + std::cout << "NULL" << "-" ; + } + std::cout << std::endl << std::endl; + std::cout << "exit distances: \n "; + + for(it2 = (*it).second.distances.begin(); it2 != (*it).second.distances.end(); it2++) { + std::cout << (*it2).first << " (" << (*it2).second.distance << ")" ; + if(it2->second.exit_edge) { + std::cout <<"subroom "<< it2->second.GetSubRoom()->GetRoomID() << "-" << (*it2).second.GetSubRoom()->GetSubRoomID() << "next vertex: " << (*it2).second.GetDest()->id <<" \n"; + } else { + std::cout << std::endl; + } + } + } } /** @@ -455,36 +455,37 @@ void RoutingGraph::print() map <int, Vertex> * RoutingGraph::GetAllVertexes() { - return &vertexes; + return &vertexes; }; Vertex * RoutingGraph::GetVertex(int id) { - map<int, Vertex>::iterator it; - it = vertexes.find(id); - if(it != vertexes.end()) { - return &it->second; - } else { - return NULL; - } + map<int, Vertex>::iterator it; + it = vertexes.find(id); + if(it != vertexes.end()) { + return &it->second; + } else { + return NULL; + } }; /**************************************** * Class Vertex ***************************************/ -ExitDistance Vertex::getShortestExit() { - map<int, ExitDistance>::iterator it; - ExitDistance return_var; - - return_var.distance = INFINITY; - for(it = distances.begin(); it != distances.end(); it++) { - if((*it).second.distance < return_var.distance) { - return_var = it->second; - } - } - return return_var; +ExitDistance Vertex::getShortestExit() +{ + map<int, ExitDistance>::iterator it; + ExitDistance return_var; + + return_var.distance = INFINITY; + for(it = distances.begin(); it != distances.end(); it++) { + if((*it).second.distance < return_var.distance) { + return_var = it->second; + } + } + return return_var; } @@ -494,53 +495,53 @@ ExitDistance Vertex::getShortestExit() { SubRoom * ExitDistance::GetSubRoom() const { - if(exit_edge) - return exit_edge->sub; - else - return NULL; + if(exit_edge) + return exit_edge->sub; + else + return NULL; } Vertex * ExitDistance::GetDest() const { - if(exit_edge && exit_edge->dest) { - return exit_edge->dest; - } else { - if(exit_vertex) - return exit_vertex; - else - return NULL; - } + if(exit_edge && exit_edge->dest) { + return exit_edge->dest; + } else { + if(exit_vertex) + return exit_vertex; + else + return NULL; + } } Vertex * ExitDistance::GetSrc() const { - if(exit_edge) { - // std::cout<< "edge " << exit_edge << std::endl; - if(exit_edge->src) { - // std::cout<< " src " << exit_edge->src << std::endl; - return exit_edge->src; - } - else { return NULL;} - } - else - return NULL; + if(exit_edge) { + // std::cout<< "edge " << exit_edge << std::endl; + if(exit_edge->src) { + // std::cout<< " src " << exit_edge->src << std::endl; + return exit_edge->src; + } else { + return NULL; + } + } else + return NULL; } ExitDistance::~ExitDistance() { - // if(!GetSrc() && exit_edge != NULL) - // { - // delete exit_edge; - // } + // if(!GetSrc() && exit_edge != NULL) + // { + // delete exit_edge; + // } } ExitDistance::ExitDistance() { - distance = 0.0; - exit_edge = NULL; - exit_vertex = NULL; + distance = 0.0; + exit_edge = NULL; + exit_vertex = NULL; } diff --git a/routing/graph/RoutingGraph.h b/routing/graph/RoutingGraph.h index 02e179050d010453548e6720f27c93bd48194691..1d0cd888b75868163591dd7b5bc8850ae54cc072 100644 --- a/routing/graph/RoutingGraph.h +++ b/routing/graph/RoutingGraph.h @@ -16,7 +16,7 @@ struct Edge; -struct ExitDistance; +struct ExitDistance; struct Vertex; class Pedestrian; @@ -30,96 +30,93 @@ class Room; class RoutingGraph { - public: - /**************************** - * Constructors & Destructors - ****************************/ +public: + /**************************** + * Constructors & Destructors + ****************************/ - RoutingGraph(); - RoutingGraph(Building * b); - RoutingGraph(RoutingGraph * orig); + RoutingGraph(); + RoutingGraph(Building * b); + RoutingGraph(RoutingGraph * orig); - virtual ~RoutingGraph(); + virtual ~RoutingGraph(); - /************************** - * init functions for Graph building - **************************/ - RoutingGraph * BuildGraph(); + /************************** + * init functions for Graph building + **************************/ + RoutingGraph * BuildGraph(); - // debug - void print(); + // debug + void print(); - /*************************** - * Routing helpers - **************************/ + /*************************** + * Routing helpers + **************************/ - ExitDistance GetNextDestination(int nav_line_index, Pedestrian * p ); - ExitDistance GetNextDestination(Pedestrian * p); - void closeDoor(int id); + ExitDistance GetNextDestination(int nav_line_index, Pedestrian * p ); + ExitDistance GetNextDestination(Pedestrian * p); + void closeDoor(int id); - /** - * Getter and Setter - */ - Vertex * GetVertex(int id); - std::map<int,Vertex> * GetAllVertexes(); + /** + * Getter and Setter + */ + Vertex * GetVertex(int id); + std::map<int,Vertex> * GetAllVertexes(); - private: +private: - Building * building; - std::map<int, Vertex> vertexes; + Building * building; + std::map<int, Vertex> vertexes; - int addVertex(NavLine * nav_line, bool exit = false); - void removeVertex(Vertex * remove_vertex); - void processSubroom(SubRoom * sub); - void addEdge(Vertex * v1, Vertex * v2, SubRoom * sub); - bool checkVisibility(Line * l1, Line * l2, SubRoom * sub); + int addVertex(NavLine * nav_line, bool exit = false); + void removeVertex(Vertex * remove_vertex); + void processSubroom(SubRoom * sub); + void addEdge(Vertex * v1, Vertex * v2, SubRoom * sub); + bool checkVisibility(Line * l1, Line * l2, SubRoom * sub); - bool checkVisibility(Point& p1, Point& p2, SubRoom * sub); - bool checkVisibility(Pedestrian * p, NavLine* l, SubRoom * sub); - void calculateDistancesForExit(Vertex * act_vertex); - void calculateDistances(Vertex * exit, Vertex * last_vertex, Vertex * act_vertex, double act_distance); + bool checkVisibility(Point& p1, Point& p2, SubRoom * sub); + bool checkVisibility(Pedestrian * p, NavLine* l, SubRoom * sub); + void calculateDistancesForExit(Vertex * act_vertex); + void calculateDistances(Vertex * exit, Vertex * last_vertex, Vertex * act_vertex, double act_distance); }; -struct Edge -{ +struct Edge { public: - Vertex * dest; - Vertex * src; - double distance; - SubRoom * sub; + Vertex * dest; + Vertex * src; + double distance; + SubRoom * sub; }; -struct ExitDistance -{ +struct ExitDistance { public: - double distance; - Edge * exit_edge; - Vertex * exit_vertex; + double distance; + Edge * exit_edge; + Vertex * exit_vertex; - ExitDistance(); + ExitDistance(); - ~ExitDistance(); - SubRoom * GetSubRoom() const; - Vertex * GetDest() const; - Vertex * GetSrc() const; + ~ExitDistance(); + SubRoom * GetSubRoom() const; + Vertex * GetDest() const; + Vertex * GetSrc() const; }; -struct Vertex -{ +struct Vertex { public: - NavLine * nav_line; - int id; - bool exit; - std::map<int, Edge> edges; - std::map<int, ExitDistance> distances; + NavLine * nav_line; + int id; + bool exit; + std::map<int, Edge> edges; + std::map<int, ExitDistance> distances; - ExitDistance getShortestExit(); + ExitDistance getShortestExit(); }; diff --git a/routing/graph/RoutingGraphStorage.cpp b/routing/graph/RoutingGraphStorage.cpp index 82fb15aa6a5729f906f83b1b6850e45ffc213ea0..9d6cbad9cc371f8a6540c2b168cbbf64cf9a8a77 100644 --- a/routing/graph/RoutingGraphStorage.cpp +++ b/routing/graph/RoutingGraphStorage.cpp @@ -19,68 +19,68 @@ RoutingGraphStorage::RoutingGraphStorage() RoutingGraphStorage::~RoutingGraphStorage() { - map<set<int>, RoutingGraph*>::iterator it; - - for(it = graphs.begin(); it != graphs.end(); it++) { - delete it->second; - - } - + map<set<int>, RoutingGraph*>::iterator it; + + for(it = graphs.begin(); it != graphs.end(); it++) { + delete it->second; + + } + } void RoutingGraphStorage::init(Building * b) { - //create the first RoutingGraph with empty set as Key (no door closed right at the beginning + //create the first RoutingGraph with empty set as Key (no door closed right at the beginning - graphs[empty_set] = new RoutingGraph(b); + graphs[empty_set] = new RoutingGraph(b); } RoutingGraph * RoutingGraphStorage::GetGraph(set<int> closed_doors) { - map<set<int>, RoutingGraph*>::iterator it; - // check if the graph with closed doors already exists - it = graphs.find(closed_doors); - if(it != graphs.end()) { - return it->second; - } - - // find the biggest existing subset - - GenerateNewGraph(closed_doors); - - return graphs[closed_doors]; + map<set<int>, RoutingGraph*>::iterator it; + // check if the graph with closed doors already exists + it = graphs.find(closed_doors); + if(it != graphs.end()) { + return it->second; + } + + // find the biggest existing subset + + GenerateNewGraph(closed_doors); + + return graphs[closed_doors]; } void RoutingGraphStorage::GenerateNewGraph(set<int> iset, set<int> from) { - set<int>::iterator it; - graphs[iset] = new RoutingGraph(GetGraph(from)); - - for(it = iset.begin(); it != iset.end(); it++) { - //check if UniqueID is already closed in the "from" graph - if(from.find(*it) == from.end()) { - graphs[iset]->closeDoor(*it); - - } - - } - return; - + set<int>::iterator it; + graphs[iset] = new RoutingGraph(GetGraph(from)); + + for(it = iset.begin(); it != iset.end(); it++) { + //check if UniqueID is already closed in the "from" graph + if(from.find(*it) == from.end()) { + graphs[iset]->closeDoor(*it); + + } + + } + return; + } /** * Returns the biggest subset for which a graph already exists * not finished yet ;) */ -set<int> RoutingGraphStorage::GetBiggestSubSet(set<int> iset) const +set<int> RoutingGraphStorage::GetBiggestSubSet(set<int> iset) const { - set<int> oset; - for(int i = iset.size(); i > 1; i--){ - //check all subsets of size i + set<int> oset; + for(int i = iset.size(); i > 1; i--) { + //check all subsets of size i + + } + return oset; - } - return oset; - } diff --git a/routing/graph/RoutingGraphStorage.h b/routing/graph/RoutingGraphStorage.h index f8a06d40ac7f29d2ccf4156617dcda0a32f60db3..769459f5213ad15e343288b39f7993e47766f28d 100644 --- a/routing/graph/RoutingGraphStorage.h +++ b/routing/graph/RoutingGraphStorage.h @@ -13,30 +13,29 @@ #include <set> -class RoutingGraphStorage -{ - - public: - RoutingGraphStorage(); - ~RoutingGraphStorage(); - void init(Building * b); - RoutingGraph * GetGraph(std::set<int> closed_doors); - - - - private: - std::map<std::set<int>, RoutingGraph*> graphs; - std::set<int> empty_set; - // do not use this function now - std::set<int> GetBiggestSubSet(std::set<int> iset) const; - - /** - * @param iset - * @param from - */ - void GenerateNewGraph(std::set<int> iset, std::set<int> from = std::set<int>()); - - - +class RoutingGraphStorage { + +public: + RoutingGraphStorage(); + ~RoutingGraphStorage(); + void init(Building * b); + RoutingGraph * GetGraph(std::set<int> closed_doors); + + + +private: + std::map<std::set<int>, RoutingGraph*> graphs; + std::set<int> empty_set; + // do not use this function now + std::set<int> GetBiggestSubSet(std::set<int> iset) const; + + /** + * @param iset + * @param from + */ + void GenerateNewGraph(std::set<int> iset, std::set<int> from = std::set<int>()); + + + }; #endif /* ROUTINGGRAPHSTORAGE_H_ */ diff --git a/routing/mesh/Mesh.cpp b/routing/mesh/Mesh.cpp index 3d628697b5803d86e4acab39f31572a6cf807f37..def7eb06609eef688be164a4adb6d6ea47f9e13f 100644 --- a/routing/mesh/Mesh.cpp +++ b/routing/mesh/Mesh.cpp @@ -8,139 +8,150 @@ #include "Mesh.h" #include <iostream> -MeshEdge::MeshEdge(int n1,int n2,int c1, int c2,Point p1,Point p2){ - _n1=n1; - _n2=n2; - _c1=c1; - _c2=c2; - SetPoint1(p1); - SetPoint2(p2); +MeshEdge::MeshEdge(int n1,int n2,int c1, int c2,Point p1,Point p2) +{ + _n1=n1; + _n2=n2; + _c1=c1; + _c2=c2; + SetPoint1(p1); + SetPoint2(p2); } MeshCell::MeshCell(double midx,double midy,std::vector<int> node_id, - double *normvec,std::vector<int> edge_id, - std::vector<int> wall_id,int id){ - //_midx=midx; - //_midy=midy; - _mid=Point(midx,midy); - _node_id=node_id; - for(int i=0;i<3;i++) - _normvec[i]=normvec[i]; - _edge_id=edge_id; - _wall_id=wall_id; - _tc_id=id; + double *normvec,std::vector<int> edge_id, + std::vector<int> wall_id,int id) +{ + //_midx=midx; + //_midy=midy; + _mid=Point(midx,midy); + _node_id=node_id; + for(int i=0; i<3; i++) + _normvec[i]=normvec[i]; + _edge_id=edge_id; + _wall_id=wall_id; + _tc_id=id; } -MeshCell::~MeshCell(){ - //delete[] _normvec; +MeshCell::~MeshCell() +{ + //delete[] _normvec; } -MeshCellGroup::MeshCellGroup(std::string groupname,std::vector<MeshCell*> cells){ - _groupname=groupname; - _cells=cells; +MeshCellGroup::MeshCellGroup(std::string groupname,std::vector<MeshCell*> cells) +{ + _groupname=groupname; + _cells=cells; } -MeshCellGroup::~MeshCellGroup(){ - for(unsigned int i=0;i<_cells.size();i++) - delete _cells[i]; +MeshCellGroup::~MeshCellGroup() +{ + for(unsigned int i=0; i<_cells.size(); i++) + delete _cells[i]; } -std::vector<MeshCell*> MeshCellGroup::GetCells()const{ - return _cells; +std::vector<MeshCell*> MeshCellGroup::GetCells()const +{ + return _cells; } -MeshData::MeshData(){ - _mNodes=std::vector<Point*>(); - _mEdges=std::vector<MeshEdge*>(); - _mObstacles=std::vector<MeshEdge*>(); - _mCellGroups=std::vector<MeshCellGroup*>(); - _mCellCount=0; +MeshData::MeshData() +{ + _mNodes=std::vector<Point*>(); + _mEdges=std::vector<MeshEdge*>(); + _mObstacles=std::vector<MeshEdge*>(); + _mCellGroups=std::vector<MeshCellGroup*>(); + _mCellCount=0; } -MeshData::~MeshData(){ - for(unsigned int i=0;i<_mNodes.size();i++) - delete _mNodes[i]; - for(unsigned int i=0;i<_mEdges.size();i++) - delete _mEdges[i]; - for(unsigned int i=0;i<_mObstacles.size();i++) - delete _mObstacles[i]; - for(unsigned int i=0;i<_mCellGroups.size();i++) - delete _mCellGroups[i]; +MeshData::~MeshData() +{ + for(unsigned int i=0; i<_mNodes.size(); i++) + delete _mNodes[i]; + for(unsigned int i=0; i<_mEdges.size(); i++) + delete _mEdges[i]; + for(unsigned int i=0; i<_mObstacles.size(); i++) + delete _mObstacles[i]; + for(unsigned int i=0; i<_mCellGroups.size(); i++) + delete _mCellGroups[i]; } -unsigned int Calc_CellCount(std::vector<MeshCellGroup*> mcg){ - unsigned int count=0; - for (unsigned int i=0;i<mcg.size();i++) - count+=mcg.at(i)->GetCells().size(); +unsigned int Calc_CellCount(std::vector<MeshCellGroup*> mcg) +{ + unsigned int count=0; + for (unsigned int i=0; i<mcg.size(); i++) + count+=mcg.at(i)->GetCells().size(); - return count; + return count; } MeshData::MeshData(std::vector<Point*> mn,std::vector<MeshEdge*> me, - std::vector<MeshEdge*> moe,std::vector<MeshCellGroup*> mcg){ - _mNodes=mn; - _mEdges=me; - _mObstacles=moe; - _mCellGroups=mcg; - _mCellCount=Calc_CellCount(mcg); + std::vector<MeshEdge*> moe,std::vector<MeshCellGroup*> mcg) +{ + _mNodes=mn; + _mEdges=me; + _mObstacles=moe; + _mCellGroups=mcg; + _mCellCount=Calc_CellCount(mcg); } -MeshCell* MeshData::GetCellAtPos( int tpos)const{ - if( tpos<0 || tpos>= (int)this->GetCellCount()) - return NULL; - else{ - for(unsigned int i=0;i<_mCellGroups.size();i++){ - if(tpos< (int)_mCellGroups.at(i)->GetCells().size()){ - return _mCellGroups.at(i)->GetCells().at(tpos); - } - else{ - tpos-=_mCellGroups.at(i)->GetCells().size(); - } - } - - return NULL; - } +MeshCell* MeshData::GetCellAtPos( int tpos)const +{ + if( tpos<0 || tpos>= (int)this->GetCellCount()) + return NULL; + else { + for(unsigned int i=0; i<_mCellGroups.size(); i++) { + if(tpos< (int)_mCellGroups.at(i)->GetCells().size()) { + return _mCellGroups.at(i)->GetCells().at(tpos); + } else { + tpos-=_mCellGroups.at(i)->GetCells().size(); + } + } + + return NULL; + } } - MeshCell* MeshData::FindCell(Point test, int& cell_id)const{ - - int tmp_id=-1; - std::vector<MeshCellGroup*>::const_iterator it_g; - for(it_g=_mCellGroups.begin();it_g!=_mCellGroups.end();it_g++){ - std::vector<MeshCell*>::const_iterator it_c; - std::vector<MeshCell*> act_cg=(*it_g)->GetCells(); - for(it_c=act_cg.begin();it_c!=act_cg.end();it_c++){ - bool found=true; - std::vector<int> act_n=(*it_c)->GetNodes(); - int count_nodes=act_n.size(); - double n1x= _mNodes.at(act_n.at(0))->GetX(); - double n1y= _mNodes.at(act_n.at(0))->GetY(); - - for(int pos=0;pos<count_nodes;pos++){ - double n2x= _mNodes.at(act_n.at((pos+1)%count_nodes))->GetX(); - double n2y= _mNodes.at(act_n.at((pos+1)%count_nodes))->GetY(); - - Point temp_nxny(n2y-n1y,n1x-n2x); - Point temp_xy=test-Point(n1x,n1y); - - // if(abs(temp_xy.ScalarP(temp_nxny))<J_EPS) - // Log->Write("Point near to line"); - - if (temp_xy.ScalarP(temp_nxny)>J_EPS){ - found=false; - break; - } - n1x=n2x; - n1y=n2y; - } - tmp_id++; - if (found){ - cell_id=tmp_id; - return (*it_c); - } - - } - } - // Point test is in no polygon of MeshData - cell_id=-1; - return NULL; +MeshCell* MeshData::FindCell(Point test, int& cell_id)const +{ + + int tmp_id=-1; + std::vector<MeshCellGroup*>::const_iterator it_g; + for(it_g=_mCellGroups.begin(); it_g!=_mCellGroups.end(); it_g++) { + std::vector<MeshCell*>::const_iterator it_c; + std::vector<MeshCell*> act_cg=(*it_g)->GetCells(); + for(it_c=act_cg.begin(); it_c!=act_cg.end(); it_c++) { + bool found=true; + std::vector<int> act_n=(*it_c)->GetNodes(); + int count_nodes=act_n.size(); + double n1x= _mNodes.at(act_n.at(0))->GetX(); + double n1y= _mNodes.at(act_n.at(0))->GetY(); + + for(int pos=0; pos<count_nodes; pos++) { + double n2x= _mNodes.at(act_n.at((pos+1)%count_nodes))->GetX(); + double n2y= _mNodes.at(act_n.at((pos+1)%count_nodes))->GetY(); + + Point temp_nxny(n2y-n1y,n1x-n2x); + Point temp_xy=test-Point(n1x,n1y); + + // if(abs(temp_xy.ScalarP(temp_nxny))<J_EPS) + // Log->Write("Point near to line"); + + if (temp_xy.ScalarP(temp_nxny)>J_EPS) { + found=false; + break; + } + n1x=n2x; + n1y=n2y; + } + tmp_id++; + if (found) { + cell_id=tmp_id; + return (*it_c); + } + + } + } + // Point test is in no polygon of MeshData + cell_id=-1; + return NULL; } /* std::istream& operator>>(std::istream& is, MeshNode& mn){ diff --git a/routing/mesh/Mesh.h b/routing/mesh/Mesh.h index 70340a91cfa0e3efc5d82d9b38fef8eb6b901391..75c25d87bc19e55b9e6ec7fdd55a01ece62b495a 100644 --- a/routing/mesh/Mesh.h +++ b/routing/mesh/Mesh.h @@ -19,77 +19,103 @@ class MeshCell; class MeshCellGroup; class Crossing; -class MeshData{ - public: - MeshData(); - ~MeshData(); - MeshData(std::vector<Point*>,std::vector<MeshEdge*>, - std::vector<MeshEdge*>,std::vector<MeshCellGroup*>); - std::vector<Point*> GetNodes()const{return _mNodes;} - std::vector<MeshEdge*> GetEdges()const{return _mEdges;} - std::vector<MeshEdge*> GetObstacles()const{return _mObstacles;} - std::vector<MeshCellGroup*> GetCellGroups()const{return _mCellGroups;} - unsigned int GetCellCount()const{return _mCellCount;}; +class MeshData { +public: + MeshData(); + ~MeshData(); + MeshData(std::vector<Point*>,std::vector<MeshEdge*>, + std::vector<MeshEdge*>,std::vector<MeshCellGroup*>); + std::vector<Point*> GetNodes()const { + return _mNodes; + } + std::vector<MeshEdge*> GetEdges()const { + return _mEdges; + } + std::vector<MeshEdge*> GetObstacles()const { + return _mObstacles; + } + std::vector<MeshCellGroup*> GetCellGroups()const { + return _mCellGroups; + } + unsigned int GetCellCount()const { + return _mCellCount; + }; - MeshCell* GetCellAtPos(int tpos)const; + MeshCell* GetCellAtPos(int tpos)const; - MeshCell* FindCell(Point testp,int& cell_id)const; + MeshCell* FindCell(Point testp,int& cell_id)const; - private: - std::vector<Point*> _mNodes; - std::vector<MeshEdge*> _mEdges; - std::vector<MeshEdge*> _mObstacles; - std::vector<MeshCellGroup*> _mCellGroups; - unsigned int _mCellCount; +private: + std::vector<Point*> _mNodes; + std::vector<MeshEdge*> _mEdges; + std::vector<MeshEdge*> _mObstacles; + std::vector<MeshCellGroup*> _mCellGroups; + unsigned int _mCellCount; }; -class MeshEdge:public Crossing{ - public: - MeshEdge(int,int,int,int,Point p1=Point(),Point p2=Point());//:Line(p1,p2); - int GetNode1()const{return _n1;}; - int GetNode2()const{return _n2;}; - int GetCell1()const{return _c1;}; - int GetCell2()const{return _c2;}; - //friend std::istream& operator>>(std::istream& is, MeshEdge& mn); - private: - int _n1; //ID of Node 1 - int _n2; //ID of Node 2 - int _c1; //ID of Cell 1 - int _c2; //ID of Cell 2 +class MeshEdge:public Crossing { +public: + MeshEdge(int,int,int,int,Point p1=Point(),Point p2=Point());//:Line(p1,p2); + int GetNode1()const { + return _n1; + }; + int GetNode2()const { + return _n2; + }; + int GetCell1()const { + return _c1; + }; + int GetCell2()const { + return _c2; + }; + //friend std::istream& operator>>(std::istream& is, MeshEdge& mn); +private: + int _n1; //ID of Node 1 + int _n2; //ID of Node 2 + int _c1; //ID of Cell 1 + int _c2; //ID of Cell 2 }; -class MeshCell{ - public: - MeshCell(double,double,std::vector<int>, - double*,std::vector<int>,std::vector<int>,int); - ~MeshCell(); - //double get_midx(){return _midx;}; - //double get_midy(){return _midy;}; - Point GetMidpoint()const{return _mid;}; - std::vector<int> GetNodes()const{return _node_id;}; - std::vector<int> GetEdges()const{return _edge_id;}; - int GetID()const{return _tc_id;}; - private: - //double _midx; - //double _midy; - Point _mid; - std::vector<int> _node_id; - //double *_normvec; - double _normvec[3]; - std::vector<int> _edge_id; - std::vector<int> _wall_id; - int _tc_id;//Cell ID unique for all cells in building +class MeshCell { +public: + MeshCell(double,double,std::vector<int>, + double*,std::vector<int>,std::vector<int>,int); + ~MeshCell(); + //double get_midx(){return _midx;}; + //double get_midy(){return _midy;}; + Point GetMidpoint()const { + return _mid; + }; + std::vector<int> GetNodes()const { + return _node_id; + }; + std::vector<int> GetEdges()const { + return _edge_id; + }; + int GetID()const { + return _tc_id; + }; +private: + //double _midx; + //double _midy; + Point _mid; + std::vector<int> _node_id; + //double *_normvec; + double _normvec[3]; + std::vector<int> _edge_id; + std::vector<int> _wall_id; + int _tc_id;//Cell ID unique for all cells in building }; -class MeshCellGroup{ - public: - MeshCellGroup(std::string,std::vector<MeshCell*>); - ~MeshCellGroup(); - std::vector<MeshCell*> GetCells()const; - private: - std::string _groupname; - std::vector<MeshCell*> _cells; +class MeshCellGroup { +public: + MeshCellGroup(std::string,std::vector<MeshCell*>); + ~MeshCellGroup(); + std::vector<MeshCell*> GetCells()const; +private: + std::string _groupname; + std::vector<MeshCell*> _cells; }; unsigned int Calc_CellCount(std::vector<MeshCellGroup*> mcg); diff --git a/tinyxml/tinystr.cpp b/tinyxml/tinystr.cpp index 186b06c81f2b38043540e4f6fb21444d13f7261d..36ce31016e1aa20242b6f35c1970a4ae079da3ab 100644 --- a/tinyxml/tinystr.cpp +++ b/tinyxml/tinystr.cpp @@ -36,75 +36,70 @@ TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } }; void TiXmlString::reserve (size_type cap) { - if (cap > capacity()) - { - TiXmlString tmp; - tmp.init(length(), cap); - memcpy(tmp.start(), data(), length()); - swap(tmp); - } + if (cap > capacity()) { + TiXmlString tmp; + tmp.init(length(), cap); + memcpy(tmp.start(), data(), length()); + swap(tmp); + } } TiXmlString& TiXmlString::assign(const char* str, size_type len) { - size_type cap = capacity(); - if (len > cap || cap > 3*(len + 8)) - { - TiXmlString tmp; - tmp.init(len); - memcpy(tmp.start(), str, len); - swap(tmp); - } - else - { - memmove(start(), str, len); - set_size(len); - } - return *this; + size_type cap = capacity(); + if (len > cap || cap > 3*(len + 8)) { + TiXmlString tmp; + tmp.init(len); + memcpy(tmp.start(), str, len); + swap(tmp); + } else { + memmove(start(), str, len); + set_size(len); + } + return *this; } TiXmlString& TiXmlString::append(const char* str, size_type len) { - size_type newsize = length() + len; - if (newsize > capacity()) - { - reserve (newsize + capacity()); - } - memmove(finish(), str, len); - set_size(newsize); - return *this; + size_type newsize = length() + len; + if (newsize > capacity()) { + reserve (newsize + capacity()); + } + memmove(finish(), str, len); + set_size(newsize); + return *this; } TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) { - TiXmlString tmp; - tmp.reserve(a.length() + b.length()); - tmp += a; - tmp += b; - return tmp; + TiXmlString tmp; + tmp.reserve(a.length() + b.length()); + tmp += a; + tmp += b; + return tmp; } TiXmlString operator + (const TiXmlString & a, const char* b) { - TiXmlString tmp; - TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) ); - tmp.reserve(a.length() + b_len); - tmp += a; - tmp.append(b, b_len); - return tmp; + TiXmlString tmp; + TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) ); + tmp.reserve(a.length() + b_len); + tmp += a; + tmp.append(b, b_len); + return tmp; } TiXmlString operator + (const char* a, const TiXmlString & b) { - TiXmlString tmp; - TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) ); - tmp.reserve(a_len + b.length()); - tmp.append(a, a_len); - tmp += b; - return tmp; + TiXmlString tmp; + TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) ); + tmp.reserve(a_len + b.length()); + tmp.append(a, a_len); + tmp += b; + return tmp; } diff --git a/tinyxml/tinystr.h b/tinyxml/tinystr.h index db5b5130729cfa2f2ce1f081ea7e100ccdb4ad77..f2dbe58cc532a4fd1d96f2fef40ab866037ccf01 100644 --- a/tinyxml/tinystr.h +++ b/tinyxml/tinystr.h @@ -52,225 +52,244 @@ The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase a string and there's no more room, we allocate a buffer twice as big as we need. */ -class TiXmlString -{ - public : - // The size type used - typedef size_t size_type; - - // Error value for find primitive - static const size_type npos; // = -1; - - - // TiXmlString empty constructor - TiXmlString () : rep_(&nullrep_) - { - } - - // TiXmlString copy constructor - TiXmlString ( const TiXmlString & copy) : rep_(0) - { - init(copy.length()); - memcpy(start(), copy.data(), length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) - { - init( static_cast<size_type>( strlen(copy) )); - memcpy(start(), copy, length()); - } - - // TiXmlString constructor, based on a string - TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) - { - init(len); - memcpy(start(), str, len); - } - - // TiXmlString destructor - ~TiXmlString () - { - quit(); - } - - TiXmlString& operator = (const char * copy) - { - return assign( copy, (size_type)strlen(copy)); - } - - TiXmlString& operator = (const TiXmlString & copy) - { - return assign(copy.start(), copy.length()); - } - - - // += operator. Maps to append - TiXmlString& operator += (const char * suffix) - { - return append(suffix, static_cast<size_type>( strlen(suffix) )); - } - - // += operator. Maps to append - TiXmlString& operator += (char single) - { - return append(&single, 1); - } - - // += operator. Maps to append - TiXmlString& operator += (const TiXmlString & suffix) - { - return append(suffix.data(), suffix.length()); - } - - - // Convert a TiXmlString into a null-terminated char * - const char * c_str () const { return rep_->str; } - - // Convert a TiXmlString into a char * (need not be null terminated). - const char * data () const { return rep_->str; } - - // Return the length of a TiXmlString - size_type length () const { return rep_->size; } - - // Alias for length() - size_type size () const { return rep_->size; } - - // Checks if a TiXmlString is empty - bool empty () const { return rep_->size == 0; } - - // Return capacity of string - size_type capacity () const { return rep_->capacity; } - - - // single char extraction - const char& at (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // [] operator - char& operator [] (size_type index) const - { - assert( index < length() ); - return rep_->str[ index ]; - } - - // find a char in a string. Return TiXmlString::npos if not found - size_type find (char lookup) const - { - return find(lookup, 0); - } - - // find a char in a string from an offset. Return TiXmlString::npos if not found - size_type find (char tofind, size_type offset) const - { - if (offset >= length()) return npos; - - for (const char* p = c_str() + offset; *p != '\0'; ++p) - { - if (*p == tofind) return static_cast< size_type >( p - c_str() ); - } - return npos; - } - - void clear () - { - //Lee: - //The original was just too strange, though correct: - // TiXmlString().swap(*this); - //Instead use the quit & re-init: - quit(); - init(0,0); - } - - /* Function to reserve a big amount of data when we know we'll need it. Be aware that this - function DOES NOT clear the content of the TiXmlString if any exists. - */ - void reserve (size_type cap); - - TiXmlString& assign (const char* str, size_type len); - - TiXmlString& append (const char* str, size_type len); - - void swap (TiXmlString& other) - { - Rep* r = rep_; - rep_ = other.rep_; - other.rep_ = r; - } - - private: - - void init(size_type sz) { init(sz, sz); } - void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } - char* start() const { return rep_->str; } - char* finish() const { return rep_->str + rep_->size; } - - struct Rep - { - size_type size, capacity; - char str[1]; - }; - - void init(size_type sz, size_type cap) - { - if (cap) - { - // Lee: the original form: - // rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap)); - // doesn't work in some cases of new being overloaded. Switching - // to the normal allocation, although use an 'int' for systems - // that are overly picky about structure alignment. - const size_type bytesNeeded = sizeof(Rep) + cap; - const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); - rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] ); - - rep_->str[ rep_->size = sz ] = '\0'; - rep_->capacity = cap; - } - else - { - rep_ = &nullrep_; - } - } - - void quit() - { - if (rep_ != &nullrep_) - { - // The rep_ is really an array of ints. (see the allocator, above). - // Cast it back before delete, so the compiler won't incorrectly call destructors. - delete [] ( reinterpret_cast<int*>( rep_ ) ); - } - } - - Rep * rep_; - static Rep nullrep_; +class TiXmlString { +public : + // The size type used + typedef size_t size_type; + + // Error value for find primitive + static const size_type npos; // = -1; + + + // TiXmlString empty constructor + TiXmlString () : rep_(&nullrep_) { + } + + // TiXmlString copy constructor + TiXmlString ( const TiXmlString & copy) : rep_(0) { + init(copy.length()); + memcpy(start(), copy.data(), length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) { + init( static_cast<size_type>( strlen(copy) )); + memcpy(start(), copy, length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) { + init(len); + memcpy(start(), str, len); + } + + // TiXmlString destructor + ~TiXmlString () { + quit(); + } + + TiXmlString& operator = (const char * copy) { + return assign( copy, (size_type)strlen(copy)); + } + + TiXmlString& operator = (const TiXmlString & copy) { + return assign(copy.start(), copy.length()); + } + + + // += operator. Maps to append + TiXmlString& operator += (const char * suffix) { + return append(suffix, static_cast<size_type>( strlen(suffix) )); + } + + // += operator. Maps to append + TiXmlString& operator += (char single) { + return append(&single, 1); + } + + // += operator. Maps to append + TiXmlString& operator += (const TiXmlString & suffix) { + return append(suffix.data(), suffix.length()); + } + + + // Convert a TiXmlString into a null-terminated char * + const char * c_str () const { + return rep_->str; + } + + // Convert a TiXmlString into a char * (need not be null terminated). + const char * data () const { + return rep_->str; + } + + // Return the length of a TiXmlString + size_type length () const { + return rep_->size; + } + + // Alias for length() + size_type size () const { + return rep_->size; + } + + // Checks if a TiXmlString is empty + bool empty () const { + return rep_->size == 0; + } + + // Return capacity of string + size_type capacity () const { + return rep_->capacity; + } + + + // single char extraction + const char& at (size_type index) const { + assert( index < length() ); + return rep_->str[ index ]; + } + + // [] operator + char& operator [] (size_type index) const { + assert( index < length() ); + return rep_->str[ index ]; + } + + // find a char in a string. Return TiXmlString::npos if not found + size_type find (char lookup) const { + return find(lookup, 0); + } + + // find a char in a string from an offset. Return TiXmlString::npos if not found + size_type find (char tofind, size_type offset) const { + if (offset >= length()) return npos; + + for (const char* p = c_str() + offset; *p != '\0'; ++p) { + if (*p == tofind) return static_cast< size_type >( p - c_str() ); + } + return npos; + } + + void clear () { + //Lee: + //The original was just too strange, though correct: + // TiXmlString().swap(*this); + //Instead use the quit & re-init: + quit(); + init(0,0); + } + + /* Function to reserve a big amount of data when we know we'll need it. Be aware that this + function DOES NOT clear the content of the TiXmlString if any exists. + */ + void reserve (size_type cap); + + TiXmlString& assign (const char* str, size_type len); + + TiXmlString& append (const char* str, size_type len); + + void swap (TiXmlString& other) { + Rep* r = rep_; + rep_ = other.rep_; + other.rep_ = r; + } + +private: + + void init(size_type sz) { + init(sz, sz); + } + void set_size(size_type sz) { + rep_->str[ rep_->size = sz ] = '\0'; + } + char* start() const { + return rep_->str; + } + char* finish() const { + return rep_->str + rep_->size; + } + + struct Rep { + size_type size, capacity; + char str[1]; + }; + + void init(size_type sz, size_type cap) { + if (cap) { + // Lee: the original form: + // rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap)); + // doesn't work in some cases of new being overloaded. Switching + // to the normal allocation, although use an 'int' for systems + // that are overly picky about structure alignment. + const size_type bytesNeeded = sizeof(Rep) + cap; + const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); + rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] ); + + rep_->str[ rep_->size = sz ] = '\0'; + rep_->capacity = cap; + } else { + rep_ = &nullrep_; + } + } + + void quit() { + if (rep_ != &nullrep_) { + // The rep_ is really an array of ints. (see the allocator, above). + // Cast it back before delete, so the compiler won't incorrectly call destructors. + delete [] ( reinterpret_cast<int*>( rep_ ) ); + } + } + + Rep * rep_; + static Rep nullrep_; } ; inline bool operator == (const TiXmlString & a, const TiXmlString & b) { - return ( a.length() == b.length() ) // optimization on some platforms - && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare + return ( a.length() == b.length() ) // optimization on some platforms + && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare } inline bool operator < (const TiXmlString & a, const TiXmlString & b) { - return strcmp(a.c_str(), b.c_str()) < 0; + return strcmp(a.c_str(), b.c_str()) < 0; } -inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } -inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } -inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } -inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } +inline bool operator != (const TiXmlString & a, const TiXmlString & b) +{ + return !(a == b); +} +inline bool operator > (const TiXmlString & a, const TiXmlString & b) +{ + return b < a; +} +inline bool operator <= (const TiXmlString & a, const TiXmlString & b) +{ + return !(b < a); +} +inline bool operator >= (const TiXmlString & a, const TiXmlString & b) +{ + return !(a < b); +} -inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } -inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } -inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } -inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } +inline bool operator == (const TiXmlString & a, const char* b) +{ + return strcmp(a.c_str(), b) == 0; +} +inline bool operator == (const char* a, const TiXmlString & b) +{ + return b == a; +} +inline bool operator != (const TiXmlString & a, const char* b) +{ + return !(a == b); +} +inline bool operator != (const char* a, const TiXmlString & b) +{ + return !(b == a); +} TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); TiXmlString operator + (const TiXmlString & a, const char* b); @@ -281,23 +300,20 @@ TiXmlString operator + (const char* a, const TiXmlString & b); TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. Only the operators that we need for TinyXML have been developped. */ -class TiXmlOutStream : public TiXmlString -{ - public : - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const TiXmlString & in) - { - *this += in; - return *this; - } - - // TiXmlOutStream << operator. - TiXmlOutStream & operator << (const char * in) - { - *this += in; - return *this; - } +class TiXmlOutStream : public TiXmlString { +public : + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const TiXmlString & in) { + *this += in; + return *this; + } + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const char * in) { + *this += in; + return *this; + } } ; diff --git a/tinyxml/tinyxml.cpp b/tinyxml/tinyxml.cpp index 719e460469227f5405cf40a7cd0961069f6424d3..91cfb46ca689f2b86b3dc7da617b83338bb7a522 100644 --- a/tinyxml/tinyxml.cpp +++ b/tinyxml/tinyxml.cpp @@ -38,670 +38,620 @@ bool TiXmlBase::condenseWhiteSpace = true; // Microsoft compiler security FILE* TiXmlFOpen( const char* filename, const char* mode ) { - #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - FILE* fp = 0; - errno_t err = fopen_s( &fp, filename, mode ); - if ( !err && fp ) - return fp; - return 0; - #else - return fopen( filename, mode ); - #endif +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + FILE* fp = 0; + errno_t err = fopen_s( &fp, filename, mode ); + if ( !err && fp ) + return fp; + return 0; +#else + return fopen( filename, mode ); +#endif } void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) { - int i=0; - - while( i<(int)str.length() ) - { - unsigned char c = (unsigned char) str[i]; - - if ( c == '&' - && i < ( (int)str.length() - 2 ) - && str[i+1] == '#' - && str[i+2] == 'x' ) - { - // Hexadecimal character reference. - // Pass through unchanged. - // © -- copyright symbol, for example. - // - // The -1 is a bug fix from Rob Laveaux. It keeps - // an overflow from happening if there is no ';'. - // There are actually 2 ways to exit this loop - - // while fails (error case) and break (semicolon found). - // However, there is no mechanism (currently) for - // this function to return an error. - while ( i<(int)str.length()-1 ) - { - outString->append( str.c_str() + i, 1 ); - ++i; - if ( str[i] == ';' ) - break; - } - } - else if ( c == '&' ) - { - outString->append( entity[0].str, entity[0].strLength ); - ++i; - } - else if ( c == '<' ) - { - outString->append( entity[1].str, entity[1].strLength ); - ++i; - } - else if ( c == '>' ) - { - outString->append( entity[2].str, entity[2].strLength ); - ++i; - } - else if ( c == '\"' ) - { - outString->append( entity[3].str, entity[3].strLength ); - ++i; - } - else if ( c == '\'' ) - { - outString->append( entity[4].str, entity[4].strLength ); - ++i; - } - else if ( c < 32 ) - { - // Easy pass at non-alpha/numeric/symbol - // Below 32 is symbolic. - char buf[ 32 ]; - - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); - #else - sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); - #endif - - //*ME: warning C4267: convert 'size_t' to 'int' - //*ME: Int-Cast to make compiler happy ... - outString->append( buf, (int)strlen( buf ) ); - ++i; - } - else - { - //char realc = (char) c; - //outString->append( &realc, 1 ); - *outString += (char) c; // somewhat more efficient function call. - ++i; - } - } + int i=0; + + while( i<(int)str.length() ) { + unsigned char c = (unsigned char) str[i]; + + if ( c == '&' + && i < ( (int)str.length() - 2 ) + && str[i+1] == '#' + && str[i+2] == 'x' ) { + // Hexadecimal character reference. + // Pass through unchanged. + // © -- copyright symbol, for example. + // + // The -1 is a bug fix from Rob Laveaux. It keeps + // an overflow from happening if there is no ';'. + // There are actually 2 ways to exit this loop - + // while fails (error case) and break (semicolon found). + // However, there is no mechanism (currently) for + // this function to return an error. + while ( i<(int)str.length()-1 ) { + outString->append( str.c_str() + i, 1 ); + ++i; + if ( str[i] == ';' ) + break; + } + } else if ( c == '&' ) { + outString->append( entity[0].str, entity[0].strLength ); + ++i; + } else if ( c == '<' ) { + outString->append( entity[1].str, entity[1].strLength ); + ++i; + } else if ( c == '>' ) { + outString->append( entity[2].str, entity[2].strLength ); + ++i; + } else if ( c == '\"' ) { + outString->append( entity[3].str, entity[3].strLength ); + ++i; + } else if ( c == '\'' ) { + outString->append( entity[4].str, entity[4].strLength ); + ++i; + } else if ( c < 32 ) { + // Easy pass at non-alpha/numeric/symbol + // Below 32 is symbolic. + char buf[ 32 ]; + +#if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); +#else + sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); +#endif + + //*ME: warning C4267: convert 'size_t' to 'int' + //*ME: Int-Cast to make compiler happy ... + outString->append( buf, (int)strlen( buf ) ); + ++i; + } else { + //char realc = (char) c; + //outString->append( &realc, 1 ); + *outString += (char) c; // somewhat more efficient function call. + ++i; + } + } } TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() { - parent = 0; - type = _type; - firstChild = 0; - lastChild = 0; - prev = 0; - next = 0; + parent = 0; + type = _type; + firstChild = 0; + lastChild = 0; + prev = 0; + next = 0; } TiXmlNode::~TiXmlNode() { - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } + while ( node ) { + temp = node; + node = node->next; + delete temp; + } } void TiXmlNode::CopyTo( TiXmlNode* target ) const { - target->SetValue (value.c_str() ); - target->userData = userData; - target->location = location; + target->SetValue (value.c_str() ); + target->userData = userData; + target->location = location; } void TiXmlNode::Clear() { - TiXmlNode* node = firstChild; - TiXmlNode* temp = 0; + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; - while ( node ) - { - temp = node; - node = node->next; - delete temp; - } + while ( node ) { + temp = node; + node = node->next; + delete temp; + } - firstChild = 0; - lastChild = 0; + firstChild = 0; + lastChild = 0; } TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) { - assert( node->parent == 0 || node->parent == this ); - assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); + assert( node->parent == 0 || node->parent == this ); + assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); - if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - delete node; - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } + if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT ) { + delete node; + if ( GetDocument() ) + GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } - node->parent = this; + node->parent = this; - node->prev = lastChild; - node->next = 0; + node->prev = lastChild; + node->next = 0; - if ( lastChild ) - lastChild->next = node; - else - firstChild = node; // it was an empty list. + if ( lastChild ) + lastChild->next = node; + else + firstChild = node; // it was an empty list. - lastChild = node; - return node; + lastChild = node; + return node; } TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) { - if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; + if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) { + if ( GetDocument() ) + GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; - return LinkEndChild( node ); + return LinkEndChild( node ); } TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) -{ - if ( !beforeThis || beforeThis->parent != this ) { - return 0; - } - if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->next = beforeThis; - node->prev = beforeThis->prev; - if ( beforeThis->prev ) - { - beforeThis->prev->next = node; - } - else - { - assert( firstChild == beforeThis ); - firstChild = node; - } - beforeThis->prev = node; - return node; +{ + if ( !beforeThis || beforeThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) { + if ( GetDocument() ) + GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->next = beforeThis; + node->prev = beforeThis->prev; + if ( beforeThis->prev ) { + beforeThis->prev->next = node; + } else { + assert( firstChild == beforeThis ); + firstChild = node; + } + beforeThis->prev = node; + return node; } TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) { - if ( !afterThis || afterThis->parent != this ) { - return 0; - } - if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) - { - if ( GetDocument() ) - GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - TiXmlNode* node = addThis.Clone(); - if ( !node ) - return 0; - node->parent = this; - - node->prev = afterThis; - node->next = afterThis->next; - if ( afterThis->next ) - { - afterThis->next->prev = node; - } - else - { - assert( lastChild == afterThis ); - lastChild = node; - } - afterThis->next = node; - return node; + if ( !afterThis || afterThis->parent != this ) { + return 0; + } + if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT ) { + if ( GetDocument() ) + GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + TiXmlNode* node = addThis.Clone(); + if ( !node ) + return 0; + node->parent = this; + + node->prev = afterThis; + node->next = afterThis->next; + if ( afterThis->next ) { + afterThis->next->prev = node; + } else { + assert( lastChild == afterThis ); + lastChild = node; + } + afterThis->next = node; + return node; } TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) { - if ( !replaceThis ) - return 0; + if ( !replaceThis ) + return 0; - if ( replaceThis->parent != this ) - return 0; + if ( replaceThis->parent != this ) + return 0; - if ( withThis.ToDocument() ) { - // A document can never be a child. Thanks to Noam. - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } + if ( withThis.ToDocument() ) { + // A document can never be a child. Thanks to Noam. + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } - TiXmlNode* node = withThis.Clone(); - if ( !node ) - return 0; + TiXmlNode* node = withThis.Clone(); + if ( !node ) + return 0; - node->next = replaceThis->next; - node->prev = replaceThis->prev; + node->next = replaceThis->next; + node->prev = replaceThis->prev; - if ( replaceThis->next ) - replaceThis->next->prev = node; - else - lastChild = node; + if ( replaceThis->next ) + replaceThis->next->prev = node; + else + lastChild = node; - if ( replaceThis->prev ) - replaceThis->prev->next = node; - else - firstChild = node; + if ( replaceThis->prev ) + replaceThis->prev->next = node; + else + firstChild = node; - delete replaceThis; - node->parent = this; - return node; + delete replaceThis; + node->parent = this; + return node; } bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) { - if ( !removeThis ) { - return false; - } + if ( !removeThis ) { + return false; + } - if ( removeThis->parent != this ) - { - assert( 0 ); - return false; - } + if ( removeThis->parent != this ) { + assert( 0 ); + return false; + } - if ( removeThis->next ) - removeThis->next->prev = removeThis->prev; - else - lastChild = removeThis->prev; + if ( removeThis->next ) + removeThis->next->prev = removeThis->prev; + else + lastChild = removeThis->prev; - if ( removeThis->prev ) - removeThis->prev->next = removeThis->next; - else - firstChild = removeThis->next; + if ( removeThis->prev ) + removeThis->prev->next = removeThis->next; + else + firstChild = removeThis->next; - delete removeThis; - return true; + delete removeThis; + return true; } const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const { - const TiXmlNode* node; - for ( node = firstChild; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; + const TiXmlNode* node; + for ( node = firstChild; node; node = node->next ) { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; } const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const { - const TiXmlNode* node; - for ( node = lastChild; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; + const TiXmlNode* node; + for ( node = lastChild; node; node = node->prev ) { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; } const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const { - if ( !previous ) - { - return FirstChild(); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling(); - } + if ( !previous ) { + return FirstChild(); + } else { + assert( previous->parent == this ); + return previous->NextSibling(); + } } const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const { - if ( !previous ) - { - return FirstChild( val ); - } - else - { - assert( previous->parent == this ); - return previous->NextSibling( val ); - } + if ( !previous ) { + return FirstChild( val ); + } else { + assert( previous->parent == this ); + return previous->NextSibling( val ); + } } -const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const +const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const { - const TiXmlNode* node; - for ( node = next; node; node = node->next ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; + const TiXmlNode* node; + for ( node = next; node; node = node->next ) { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; } const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const { - const TiXmlNode* node; - for ( node = prev; node; node = node->prev ) - { - if ( strcmp( node->Value(), _value ) == 0 ) - return node; - } - return 0; + const TiXmlNode* node; + for ( node = prev; node; node = node->prev ) { + if ( strcmp( node->Value(), _value ) == 0 ) + return node; + } + return 0; } void TiXmlElement::RemoveAttribute( const char * name ) { - #ifdef TIXML_USE_STL - TIXML_STRING str( name ); - TiXmlAttribute* node = attributeSet.Find( str ); - #else - TiXmlAttribute* node = attributeSet.Find( name ); - #endif - if ( node ) - { - attributeSet.Remove( node ); - delete node; - } +#ifdef TIXML_USE_STL + TIXML_STRING str( name ); + TiXmlAttribute* node = attributeSet.Find( str ); +#else + TiXmlAttribute* node = attributeSet.Find( name ); +#endif + if ( node ) { + attributeSet.Remove( node ); + delete node; + } } const TiXmlElement* TiXmlNode::FirstChildElement() const { - const TiXmlNode* node; + const TiXmlNode* node; - for ( node = FirstChild(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; + for ( node = FirstChild(); + node; + node = node->NextSibling() ) { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; } const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const { - const TiXmlNode* node; + const TiXmlNode* node; - for ( node = FirstChild( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; + for ( node = FirstChild( _value ); + node; + node = node->NextSibling( _value ) ) { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; } const TiXmlElement* TiXmlNode::NextSiblingElement() const { - const TiXmlNode* node; + const TiXmlNode* node; - for ( node = NextSibling(); - node; - node = node->NextSibling() ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; + for ( node = NextSibling(); + node; + node = node->NextSibling() ) { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; } const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const { - const TiXmlNode* node; + const TiXmlNode* node; - for ( node = NextSibling( _value ); - node; - node = node->NextSibling( _value ) ) - { - if ( node->ToElement() ) - return node->ToElement(); - } - return 0; + for ( node = NextSibling( _value ); + node; + node = node->NextSibling( _value ) ) { + if ( node->ToElement() ) + return node->ToElement(); + } + return 0; } const TiXmlDocument* TiXmlNode::GetDocument() const { - const TiXmlNode* node; + const TiXmlNode* node; - for( node = this; node; node = node->parent ) - { - if ( node->ToDocument() ) - return node->ToDocument(); - } - return 0; + for( node = this; node; node = node->parent ) { + if ( node->ToDocument() ) + return node->ToDocument(); + } + return 0; } TiXmlElement::TiXmlElement (const char * _value) - : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) { - firstChild = lastChild = 0; - value = _value; + firstChild = lastChild = 0; + value = _value; } #ifdef TIXML_USE_STL -TiXmlElement::TiXmlElement( const std::string& _value ) - : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +TiXmlElement::TiXmlElement( const std::string& _value ) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) { - firstChild = lastChild = 0; - value = _value; + firstChild = lastChild = 0; + value = _value; } #endif TiXmlElement::TiXmlElement( const TiXmlElement& copy) - : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) { - firstChild = lastChild = 0; - copy.CopyTo( this ); + firstChild = lastChild = 0; + copy.CopyTo( this ); } TiXmlElement& TiXmlElement::operator=( const TiXmlElement& base ) { - ClearThis(); - base.CopyTo( this ); - return *this; + ClearThis(); + base.CopyTo( this ); + return *this; } TiXmlElement::~TiXmlElement() { - ClearThis(); + ClearThis(); } void TiXmlElement::ClearThis() { - Clear(); - while( attributeSet.First() ) - { - TiXmlAttribute* node = attributeSet.First(); - attributeSet.Remove( node ); - delete node; - } + Clear(); + while( attributeSet.First() ) { + TiXmlAttribute* node = attributeSet.First(); + attributeSet.Remove( node ); + delete node; + } } const char* TiXmlElement::Attribute( const char* name ) const { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( node ) - return node->Value(); - return 0; + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( node ) + return node->Value(); + return 0; } #ifdef TIXML_USE_STL const std::string* TiXmlElement::Attribute( const std::string& name ) const { - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( attrib ) - return &attrib->ValueStr(); - return 0; + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( attrib ) + return &attrib->ValueStr(); + return 0; } #endif const char* TiXmlElement::Attribute( const char* name, int* i ) const { - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const char* result = 0; + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const char* result = 0; - if ( attrib ) { - result = attrib->Value(); - if ( i ) { - attrib->QueryIntValue( i ); - } - } - return result; + if ( attrib ) { + result = attrib->Value(); + if ( i ) { + attrib->QueryIntValue( i ); + } + } + return result; } #ifdef TIXML_USE_STL const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const { - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const std::string* result = 0; + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const std::string* result = 0; - if ( attrib ) { - result = &attrib->ValueStr(); - if ( i ) { - attrib->QueryIntValue( i ); - } - } - return result; + if ( attrib ) { + result = &attrib->ValueStr(); + if ( i ) { + attrib->QueryIntValue( i ); + } + } + return result; } #endif const char* TiXmlElement::Attribute( const char* name, double* d ) const { - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const char* result = 0; + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const char* result = 0; - if ( attrib ) { - result = attrib->Value(); - if ( d ) { - attrib->QueryDoubleValue( d ); - } - } - return result; + if ( attrib ) { + result = attrib->Value(); + if ( d ) { + attrib->QueryDoubleValue( d ); + } + } + return result; } #ifdef TIXML_USE_STL const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const { - const TiXmlAttribute* attrib = attributeSet.Find( name ); - const std::string* result = 0; + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const std::string* result = 0; - if ( attrib ) { - result = &attrib->ValueStr(); - if ( d ) { - attrib->QueryDoubleValue( d ); - } - } - return result; + if ( attrib ) { + result = &attrib->ValueStr(); + if ( d ) { + attrib->QueryDoubleValue( d ); + } + } + return result; } #endif int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const { - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryIntValue( ival ); + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryIntValue( ival ); } int TiXmlElement::QueryUnsignedAttribute( const char* name, unsigned* value ) const { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; - int ival = 0; - int result = node->QueryIntValue( &ival ); - *value = (unsigned)ival; - return result; + int ival = 0; + int result = node->QueryIntValue( &ival ); + *value = (unsigned)ival; + return result; } int TiXmlElement::QueryBoolAttribute( const char* name, bool* bval ) const { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - int result = TIXML_WRONG_TYPE; - if ( StringEqual( node->Value(), "true", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "yes", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "1", true, TIXML_ENCODING_UNKNOWN ) ) - { - *bval = true; - result = TIXML_SUCCESS; - } - else if ( StringEqual( node->Value(), "false", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "no", true, TIXML_ENCODING_UNKNOWN ) - || StringEqual( node->Value(), "0", true, TIXML_ENCODING_UNKNOWN ) ) - { - *bval = false; - result = TIXML_SUCCESS; - } - return result; + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + int result = TIXML_WRONG_TYPE; + if ( StringEqual( node->Value(), "true", true, TIXML_ENCODING_UNKNOWN ) + || StringEqual( node->Value(), "yes", true, TIXML_ENCODING_UNKNOWN ) + || StringEqual( node->Value(), "1", true, TIXML_ENCODING_UNKNOWN ) ) { + *bval = true; + result = TIXML_SUCCESS; + } else if ( StringEqual( node->Value(), "false", true, TIXML_ENCODING_UNKNOWN ) + || StringEqual( node->Value(), "no", true, TIXML_ENCODING_UNKNOWN ) + || StringEqual( node->Value(), "0", true, TIXML_ENCODING_UNKNOWN ) ) { + *bval = false; + result = TIXML_SUCCESS; + } + return result; } @@ -709,471 +659,447 @@ int TiXmlElement::QueryBoolAttribute( const char* name, bool* bval ) const #ifdef TIXML_USE_STL int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const { - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryIntValue( ival ); + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryIntValue( ival ); } #endif int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const { - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryDoubleValue( dval ); + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryDoubleValue( dval ); } #ifdef TIXML_USE_STL int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const { - const TiXmlAttribute* attrib = attributeSet.Find( name ); - if ( !attrib ) - return TIXML_NO_ATTRIBUTE; - return attrib->QueryDoubleValue( dval ); + const TiXmlAttribute* attrib = attributeSet.Find( name ); + if ( !attrib ) + return TIXML_NO_ATTRIBUTE; + return attrib->QueryDoubleValue( dval ); } #endif void TiXmlElement::SetAttribute( const char * name, int val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetIntValue( val ); - } +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetIntValue( val ); + } } #ifdef TIXML_USE_STL void TiXmlElement::SetAttribute( const std::string& name, int val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetIntValue( val ); - } +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetIntValue( val ); + } } #endif void TiXmlElement::SetDoubleAttribute( const char * name, double val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetDoubleValue( val ); - } +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetDoubleValue( val ); + } } #ifdef TIXML_USE_STL void TiXmlElement::SetDoubleAttribute( const std::string& name, double val ) -{ - TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); - if ( attrib ) { - attrib->SetDoubleValue( val ); - } +{ + TiXmlAttribute* attrib = attributeSet.FindOrCreate( name ); + if ( attrib ) { + attrib->SetDoubleValue( val ); + } } -#endif +#endif void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) { - TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname ); - if ( attrib ) { - attrib->SetValue( cvalue ); - } + TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname ); + if ( attrib ) { + attrib->SetValue( cvalue ); + } } #ifdef TIXML_USE_STL void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value ) { - TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name ); - if ( attrib ) { - attrib->SetValue( _value ); - } + TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name ); + if ( attrib ) { + attrib->SetValue( _value ); + } } #endif void TiXmlElement::Print( FILE* cfile, int depth ) const { - int i; - assert( cfile ); - for ( i=0; i<depth; i++ ) { - fprintf( cfile, " " ); - } - - fprintf( cfile, "<%s", value.c_str() ); - - const TiXmlAttribute* attrib; - for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() ) - { - fprintf( cfile, " " ); - attrib->Print( cfile, depth ); - } - - // There are 3 different formatting approaches: - // 1) An element without children is printed as a <foo /> node - // 2) An element with only a text child is printed as <foo> text </foo> - // 3) An element with children is printed on multiple lines. - TiXmlNode* node; - if ( !firstChild ) - { - fprintf( cfile, " />" ); - } - else if ( firstChild == lastChild && firstChild->ToText() ) - { - fprintf( cfile, ">" ); - firstChild->Print( cfile, depth + 1 ); - fprintf( cfile, "</%s>", value.c_str() ); - } - else - { - fprintf( cfile, ">" ); - - for ( node = firstChild; node; node=node->NextSibling() ) - { - if ( !node->ToText() ) - { - fprintf( cfile, "\n" ); - } - node->Print( cfile, depth+1 ); - } - fprintf( cfile, "\n" ); - for( i=0; i<depth; ++i ) { - fprintf( cfile, " " ); - } - fprintf( cfile, "</%s>", value.c_str() ); - } + int i; + assert( cfile ); + for ( i=0; i<depth; i++ ) { + fprintf( cfile, " " ); + } + + fprintf( cfile, "<%s", value.c_str() ); + + const TiXmlAttribute* attrib; + for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() ) { + fprintf( cfile, " " ); + attrib->Print( cfile, depth ); + } + + // There are 3 different formatting approaches: + // 1) An element without children is printed as a <foo /> node + // 2) An element with only a text child is printed as <foo> text </foo> + // 3) An element with children is printed on multiple lines. + TiXmlNode* node; + if ( !firstChild ) { + fprintf( cfile, " />" ); + } else if ( firstChild == lastChild && firstChild->ToText() ) { + fprintf( cfile, ">" ); + firstChild->Print( cfile, depth + 1 ); + fprintf( cfile, "</%s>", value.c_str() ); + } else { + fprintf( cfile, ">" ); + + for ( node = firstChild; node; node=node->NextSibling() ) { + if ( !node->ToText() ) { + fprintf( cfile, "\n" ); + } + node->Print( cfile, depth+1 ); + } + fprintf( cfile, "\n" ); + for( i=0; i<depth; ++i ) { + fprintf( cfile, " " ); + } + fprintf( cfile, "</%s>", value.c_str() ); + } } void TiXmlElement::CopyTo( TiXmlElement* target ) const { - // superclass: - TiXmlNode::CopyTo( target ); + // superclass: + TiXmlNode::CopyTo( target ); - // Element class: - // Clone the attributes, then clone the children. - const TiXmlAttribute* attribute = 0; - for( attribute = attributeSet.First(); - attribute; - attribute = attribute->Next() ) - { - target->SetAttribute( attribute->Name(), attribute->Value() ); - } + // Element class: + // Clone the attributes, then clone the children. + const TiXmlAttribute* attribute = 0; + for( attribute = attributeSet.First(); + attribute; + attribute = attribute->Next() ) { + target->SetAttribute( attribute->Name(), attribute->Value() ); + } - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) { + target->LinkEndChild( node->Clone() ); + } } bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const { - if ( visitor->VisitEnter( *this, attributeSet.First() ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); + if ( visitor->VisitEnter( *this, attributeSet.First() ) ) { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); } TiXmlNode* TiXmlElement::Clone() const { - TiXmlElement* clone = new TiXmlElement( Value() ); - if ( !clone ) - return 0; + TiXmlElement* clone = new TiXmlElement( Value() ); + if ( !clone ) + return 0; - CopyTo( clone ); - return clone; + CopyTo( clone ); + return clone; } const char* TiXmlElement::GetText() const { - const TiXmlNode* child = this->FirstChild(); - if ( child ) { - const TiXmlText* childText = child->ToText(); - if ( childText ) { - return childText->Value(); - } - } - return 0; + const TiXmlNode* child = this->FirstChild(); + if ( child ) { + const TiXmlText* childText = child->ToText(); + if ( childText ) { + return childText->Value(); + } + } + return 0; } TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) { - tabsize = 4; - useMicrosoftBOM = false; - ClearError(); + tabsize = 4; + useMicrosoftBOM = false; + ClearError(); } TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) { - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); } #ifdef TIXML_USE_STL TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) { - tabsize = 4; - useMicrosoftBOM = false; - value = documentName; - ClearError(); + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); } #endif TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) { - copy.CopyTo( this ); + copy.CopyTo( this ); } TiXmlDocument& TiXmlDocument::operator=( const TiXmlDocument& copy ) { - Clear(); - copy.CopyTo( this ); - return *this; + Clear(); + copy.CopyTo( this ); + return *this; } bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) { - return LoadFile( Value(), encoding ); + return LoadFile( Value(), encoding ); } bool TiXmlDocument::SaveFile() const { - return SaveFile( Value() ); + return SaveFile( Value() ); } bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) { - TIXML_STRING filename( _filename ); - value = filename; + TIXML_STRING filename( _filename ); + value = filename; - // reading in binary mode so that tinyxml can normalize the EOL - FILE* file = TiXmlFOpen( value.c_str (), "rb" ); + // reading in binary mode so that tinyxml can normalize the EOL + FILE* file = TiXmlFOpen( value.c_str (), "rb" ); - if ( file ) - { - bool result = LoadFile( file, encoding ); - fclose( file ); - return result; - } - else - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } + if ( file ) { + bool result = LoadFile( file, encoding ); + fclose( file ); + return result; + } else { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } } bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) { - if ( !file ) - { - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Delete the existing data: - Clear(); - location.Clear(); - - // Get the file size, so we can pre-allocate the string. HUGE speed impact. - long length = 0; - fseek( file, 0, SEEK_END ); - length = ftell( file ); - fseek( file, 0, SEEK_SET ); - - // Strange case, but good to handle up front. - if ( length <= 0 ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Subtle bug here. TinyXml did use fgets. But from the XML spec: - // 2.11 End-of-Line Handling - // <snip> - // <quote> - // ...the XML processor MUST behave as if it normalized all line breaks in external - // parsed entities (including the document entity) on input, before parsing, by translating - // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to - // a single #xA character. - // </quote> - // - // It is not clear fgets does that, and certainly isn't clear it works cross platform. - // Generally, you expect fgets to translate from the convention of the OS to the c/unix - // convention, and not work generally. - - /* - while( fgets( buf, sizeof(buf), file ) ) - { - data += buf; - } - */ - - char* buf = new char[ length+1 ]; - buf[0] = 0; - - if ( fread( buf, length, 1, file ) != 1 ) { - delete [] buf; - SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); - return false; - } - - // Process the buffer in place to normalize new lines. (See comment above.) - // Copies from the 'p' to 'q' pointer, where p can advance faster if - // a newline-carriage return is hit. - // - // Wikipedia: - // Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or - // CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)... - // * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others - // * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS - // * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9 - - const char* p = buf; // the read head - char* q = buf; // the write head - const char CR = 0x0d; - const char LF = 0x0a; - - buf[length] = 0; - while( *p ) { - assert( p < (buf+length) ); - assert( q <= (buf+length) ); - assert( q <= p ); - - if ( *p == CR ) { - *q++ = LF; - p++; - if ( *p == LF ) { // check for CR+LF (and skip LF) - p++; - } - } - else { - *q++ = *p++; - } - } - assert( q <= (buf+length) ); - *q = 0; - - Parse( buf, 0, encoding ); - - delete [] buf; - return !Error(); + if ( !file ) { + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Delete the existing data: + Clear(); + location.Clear(); + + // Get the file size, so we can pre-allocate the string. HUGE speed impact. + long length = 0; + fseek( file, 0, SEEK_END ); + length = ftell( file ); + fseek( file, 0, SEEK_SET ); + + // Strange case, but good to handle up front. + if ( length <= 0 ) { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Subtle bug here. TinyXml did use fgets. But from the XML spec: + // 2.11 End-of-Line Handling + // <snip> + // <quote> + // ...the XML processor MUST behave as if it normalized all line breaks in external + // parsed entities (including the document entity) on input, before parsing, by translating + // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to + // a single #xA character. + // </quote> + // + // It is not clear fgets does that, and certainly isn't clear it works cross platform. + // Generally, you expect fgets to translate from the convention of the OS to the c/unix + // convention, and not work generally. + + /* + while( fgets( buf, sizeof(buf), file ) ) + { + data += buf; + } + */ + + char* buf = new char[ length+1 ]; + buf[0] = 0; + + if ( fread( buf, length, 1, file ) != 1 ) { + delete [] buf; + SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); + return false; + } + + // Process the buffer in place to normalize new lines. (See comment above.) + // Copies from the 'p' to 'q' pointer, where p can advance faster if + // a newline-carriage return is hit. + // + // Wikipedia: + // Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or + // CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)... + // * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others + // * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS + // * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9 + + const char* p = buf; // the read head + char* q = buf; // the write head + const char CR = 0x0d; + const char LF = 0x0a; + + buf[length] = 0; + while( *p ) { + assert( p < (buf+length) ); + assert( q <= (buf+length) ); + assert( q <= p ); + + if ( *p == CR ) { + *q++ = LF; + p++; + if ( *p == LF ) { // check for CR+LF (and skip LF) + p++; + } + } else { + *q++ = *p++; + } + } + assert( q <= (buf+length) ); + *q = 0; + + Parse( buf, 0, encoding ); + + delete [] buf; + return !Error(); } bool TiXmlDocument::SaveFile( const char * filename ) const { - // The old c stuff lives on... - FILE* fp = TiXmlFOpen( filename, "w" ); - if ( fp ) - { - bool result = SaveFile( fp ); - fclose( fp ); - return result; - } - return false; + // The old c stuff lives on... + FILE* fp = TiXmlFOpen( filename, "w" ); + if ( fp ) { + bool result = SaveFile( fp ); + fclose( fp ); + return result; + } + return false; } bool TiXmlDocument::SaveFile( FILE* fp ) const { - if ( useMicrosoftBOM ) - { - const unsigned char TIXML_UTF_LEAD_0 = 0xefU; - const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; - const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + if ( useMicrosoftBOM ) { + const unsigned char TIXML_UTF_LEAD_0 = 0xefU; + const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; + const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; - fputc( TIXML_UTF_LEAD_0, fp ); - fputc( TIXML_UTF_LEAD_1, fp ); - fputc( TIXML_UTF_LEAD_2, fp ); - } - Print( fp, 0 ); - return (ferror(fp) == 0); + fputc( TIXML_UTF_LEAD_0, fp ); + fputc( TIXML_UTF_LEAD_1, fp ); + fputc( TIXML_UTF_LEAD_2, fp ); + } + Print( fp, 0 ); + return (ferror(fp) == 0); } void TiXmlDocument::CopyTo( TiXmlDocument* target ) const { - TiXmlNode::CopyTo( target ); + TiXmlNode::CopyTo( target ); - target->error = error; - target->errorId = errorId; - target->errorDesc = errorDesc; - target->tabsize = tabsize; - target->errorLocation = errorLocation; - target->useMicrosoftBOM = useMicrosoftBOM; + target->error = error; + target->errorId = errorId; + target->errorDesc = errorDesc; + target->tabsize = tabsize; + target->errorLocation = errorLocation; + target->useMicrosoftBOM = useMicrosoftBOM; - TiXmlNode* node = 0; - for ( node = firstChild; node; node = node->NextSibling() ) - { - target->LinkEndChild( node->Clone() ); - } + TiXmlNode* node = 0; + for ( node = firstChild; node; node = node->NextSibling() ) { + target->LinkEndChild( node->Clone() ); + } } TiXmlNode* TiXmlDocument::Clone() const { - TiXmlDocument* clone = new TiXmlDocument(); - if ( !clone ) - return 0; + TiXmlDocument* clone = new TiXmlDocument(); + if ( !clone ) + return 0; - CopyTo( clone ); - return clone; + CopyTo( clone ); + return clone; } void TiXmlDocument::Print( FILE* cfile, int depth ) const { - assert( cfile ); - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - node->Print( cfile, depth ); - fprintf( cfile, "\n" ); - } + assert( cfile ); + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) { + node->Print( cfile, depth ); + fprintf( cfile, "\n" ); + } } bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const { - if ( visitor->VisitEnter( *this ) ) - { - for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) - { - if ( !node->Accept( visitor ) ) - break; - } - } - return visitor->VisitExit( *this ); + if ( visitor->VisitEnter( *this ) ) { + for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) { + if ( !node->Accept( visitor ) ) + break; + } + } + return visitor->VisitExit( *this ); } const TiXmlAttribute* TiXmlAttribute::Next() const { - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( next->value.empty() && next->name.empty() ) - return 0; - return next; + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( next->value.empty() && next->name.empty() ) + return 0; + return next; } /* @@ -1189,11 +1115,11 @@ TiXmlAttribute* TiXmlAttribute::Next() const TiXmlAttribute* TiXmlAttribute::Previous() const { - // We are using knowledge of the sentinel. The sentinel - // have a value or name. - if ( prev->value.empty() && prev->name.empty() ) - return 0; - return prev; + // We are using knowledge of the sentinel. The sentinel + // have a value or name. + if ( prev->value.empty() && prev->name.empty() ) + return 0; + return prev; } /* @@ -1209,678 +1135,657 @@ TiXmlAttribute* TiXmlAttribute::Previous() void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const { - TIXML_STRING n, v; - - EncodeString( name, &n ); - EncodeString( value, &v ); - - if (value.find ('\"') == TIXML_STRING::npos) { - if ( cfile ) { - fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); - } - if ( str ) { - (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; - } - } - else { - if ( cfile ) { - fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); - } - if ( str ) { - (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; - } - } + TIXML_STRING n, v; + + EncodeString( name, &n ); + EncodeString( value, &v ); + + if (value.find ('\"') == TIXML_STRING::npos) { + if ( cfile ) { + fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; + (*str) += "=\""; + (*str) += v; + (*str) += "\""; + } + } else { + if ( cfile ) { + fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; + (*str) += "='"; + (*str) += v; + (*str) += "'"; + } + } } int TiXmlAttribute::QueryIntValue( int* ival ) const { - if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; + if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; } int TiXmlAttribute::QueryDoubleValue( double* dval ) const { - if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; + if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; } void TiXmlAttribute::SetIntValue( int _value ) { - char buf [64]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); - #else - sprintf (buf, "%d", _value); - #endif - SetValue (buf); + char buf [64]; +#if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); +#else + sprintf (buf, "%d", _value); +#endif + SetValue (buf); } void TiXmlAttribute::SetDoubleValue( double _value ) { - char buf [256]; - #if defined(TIXML_SNPRINTF) - TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value); - #else - sprintf (buf, "%g", _value); - #endif - SetValue (buf); + char buf [256]; +#if defined(TIXML_SNPRINTF) + TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value); +#else + sprintf (buf, "%g", _value); +#endif + SetValue (buf); } int TiXmlAttribute::IntValue() const { - return atoi (value.c_str ()); + return atoi (value.c_str ()); } double TiXmlAttribute::DoubleValue() const { - return atof (value.c_str ()); + return atof (value.c_str ()); } TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) { - copy.CopyTo( this ); + copy.CopyTo( this ); } TiXmlComment& TiXmlComment::operator=( const TiXmlComment& base ) { - Clear(); - base.CopyTo( this ); - return *this; + Clear(); + base.CopyTo( this ); + return *this; } void TiXmlComment::Print( FILE* cfile, int depth ) const { - assert( cfile ); - for ( int i=0; i<depth; i++ ) - { - fprintf( cfile, " " ); - } - fprintf( cfile, "<!--%s-->", value.c_str() ); + assert( cfile ); + for ( int i=0; i<depth; i++ ) { + fprintf( cfile, " " ); + } + fprintf( cfile, "<!--%s-->", value.c_str() ); } void TiXmlComment::CopyTo( TiXmlComment* target ) const { - TiXmlNode::CopyTo( target ); + TiXmlNode::CopyTo( target ); } bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const { - return visitor->Visit( *this ); + return visitor->Visit( *this ); } TiXmlNode* TiXmlComment::Clone() const { - TiXmlComment* clone = new TiXmlComment(); + TiXmlComment* clone = new TiXmlComment(); - if ( !clone ) - return 0; + if ( !clone ) + return 0; - CopyTo( clone ); - return clone; + CopyTo( clone ); + return clone; } void TiXmlText::Print( FILE* cfile, int depth ) const { - assert( cfile ); - if ( cdata ) - { - int i; - fprintf( cfile, "\n" ); - for ( i=0; i<depth; i++ ) { - fprintf( cfile, " " ); - } - fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() ); // unformatted output - } - else - { - TIXML_STRING buffer; - EncodeString( value, &buffer ); - fprintf( cfile, "%s", buffer.c_str() ); - } + assert( cfile ); + if ( cdata ) { + int i; + fprintf( cfile, "\n" ); + for ( i=0; i<depth; i++ ) { + fprintf( cfile, " " ); + } + fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() ); // unformatted output + } else { + TIXML_STRING buffer; + EncodeString( value, &buffer ); + fprintf( cfile, "%s", buffer.c_str() ); + } } void TiXmlText::CopyTo( TiXmlText* target ) const { - TiXmlNode::CopyTo( target ); - target->cdata = cdata; + TiXmlNode::CopyTo( target ); + target->cdata = cdata; } bool TiXmlText::Accept( TiXmlVisitor* visitor ) const { - return visitor->Visit( *this ); + return visitor->Visit( *this ); } TiXmlNode* TiXmlText::Clone() const -{ - TiXmlText* clone = 0; - clone = new TiXmlText( "" ); +{ + TiXmlText* clone = 0; + clone = new TiXmlText( "" ); - if ( !clone ) - return 0; + if ( !clone ) + return 0; - CopyTo( clone ); - return clone; + CopyTo( clone ); + return clone; } TiXmlDeclaration::TiXmlDeclaration( const char * _version, - const char * _encoding, - const char * _standalone ) - : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) + const char * _encoding, + const char * _standalone ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) { - version = _version; - encoding = _encoding; - standalone = _standalone; + version = _version; + encoding = _encoding; + standalone = _standalone; } #ifdef TIXML_USE_STL TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ) - : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) + const std::string& _encoding, + const std::string& _standalone ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) { - version = _version; - encoding = _encoding; - standalone = _standalone; + version = _version; + encoding = _encoding; + standalone = _standalone; } #endif TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) - : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) { - copy.CopyTo( this ); + copy.CopyTo( this ); } TiXmlDeclaration& TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) { - Clear(); - copy.CopyTo( this ); - return *this; + Clear(); + copy.CopyTo( this ); + return *this; } void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const { - if ( cfile ) fprintf( cfile, "<?xml " ); - if ( str ) (*str) += "<?xml "; - - if ( !version.empty() ) { - if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ()); - if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; } - } - if ( !encoding.empty() ) { - if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ()); - if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; } - } - if ( !standalone.empty() ) { - if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ()); - if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; } - } - if ( cfile ) fprintf( cfile, "?>" ); - if ( str ) (*str) += "?>"; + if ( cfile ) fprintf( cfile, "<?xml " ); + if ( str ) (*str) += "<?xml "; + + if ( !version.empty() ) { + if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ()); + if ( str ) { + (*str) += "version=\""; + (*str) += version; + (*str) += "\" "; + } + } + if ( !encoding.empty() ) { + if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ()); + if ( str ) { + (*str) += "encoding=\""; + (*str) += encoding; + (*str) += "\" "; + } + } + if ( !standalone.empty() ) { + if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ()); + if ( str ) { + (*str) += "standalone=\""; + (*str) += standalone; + (*str) += "\" "; + } + } + if ( cfile ) fprintf( cfile, "?>" ); + if ( str ) (*str) += "?>"; } void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const { - TiXmlNode::CopyTo( target ); + TiXmlNode::CopyTo( target ); - target->version = version; - target->encoding = encoding; - target->standalone = standalone; + target->version = version; + target->encoding = encoding; + target->standalone = standalone; } bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const { - return visitor->Visit( *this ); + return visitor->Visit( *this ); } TiXmlNode* TiXmlDeclaration::Clone() const -{ - TiXmlDeclaration* clone = new TiXmlDeclaration(); +{ + TiXmlDeclaration* clone = new TiXmlDeclaration(); - if ( !clone ) - return 0; + if ( !clone ) + return 0; - CopyTo( clone ); - return clone; + CopyTo( clone ); + return clone; } void TiXmlUnknown::Print( FILE* cfile, int depth ) const { - for ( int i=0; i<depth; i++ ) - fprintf( cfile, " " ); - fprintf( cfile, "<%s>", value.c_str() ); + for ( int i=0; i<depth; i++ ) + fprintf( cfile, " " ); + fprintf( cfile, "<%s>", value.c_str() ); } void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const { - TiXmlNode::CopyTo( target ); + TiXmlNode::CopyTo( target ); } bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const { - return visitor->Visit( *this ); + return visitor->Visit( *this ); } TiXmlNode* TiXmlUnknown::Clone() const { - TiXmlUnknown* clone = new TiXmlUnknown(); + TiXmlUnknown* clone = new TiXmlUnknown(); - if ( !clone ) - return 0; + if ( !clone ) + return 0; - CopyTo( clone ); - return clone; + CopyTo( clone ); + return clone; } TiXmlAttributeSet::TiXmlAttributeSet() { - sentinel.next = &sentinel; - sentinel.prev = &sentinel; + sentinel.next = &sentinel; + sentinel.prev = &sentinel; } TiXmlAttributeSet::~TiXmlAttributeSet() { - assert( sentinel.next == &sentinel ); - assert( sentinel.prev == &sentinel ); + assert( sentinel.next == &sentinel ); + assert( sentinel.prev == &sentinel ); } void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) { - #ifdef TIXML_USE_STL - assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. - #else - assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. - #endif +#ifdef TIXML_USE_STL + assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. +#else + assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. +#endif - addMe->next = &sentinel; - addMe->prev = sentinel.prev; + addMe->next = &sentinel; + addMe->prev = sentinel.prev; - sentinel.prev->next = addMe; - sentinel.prev = addMe; + sentinel.prev->next = addMe; + sentinel.prev = addMe; } void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) { - TiXmlAttribute* node; + TiXmlAttribute* node; - for( node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node == removeMe ) - { - node->prev->next = node->next; - node->next->prev = node->prev; - node->next = 0; - node->prev = 0; - return; - } - } - assert( 0 ); // we tried to remove a non-linked attribute. + for( node = sentinel.next; node != &sentinel; node = node->next ) { + if ( node == removeMe ) { + node->prev->next = node->next; + node->next->prev = node->prev; + node->next = 0; + node->prev = 0; + return; + } + } + assert( 0 ); // we tried to remove a non-linked attribute. } #ifdef TIXML_USE_STL TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const { - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( node->name == name ) - return node; - } - return 0; + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) { + if ( node->name == name ) + return node; + } + return 0; } TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name ) { - TiXmlAttribute* attrib = Find( _name ); - if ( !attrib ) { - attrib = new TiXmlAttribute(); - Add( attrib ); - attrib->SetName( _name ); - } - return attrib; + TiXmlAttribute* attrib = Find( _name ); + if ( !attrib ) { + attrib = new TiXmlAttribute(); + Add( attrib ); + attrib->SetName( _name ); + } + return attrib; } #endif TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const { - for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) - { - if ( strcmp( node->name.c_str(), name ) == 0 ) - return node; - } - return 0; + for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) { + if ( strcmp( node->name.c_str(), name ) == 0 ) + return node; + } + return 0; } TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name ) { - TiXmlAttribute* attrib = Find( _name ); - if ( !attrib ) { - attrib = new TiXmlAttribute(); - Add( attrib ); - attrib->SetName( _name ); - } - return attrib; + TiXmlAttribute* attrib = Find( _name ); + if ( !attrib ) { + attrib = new TiXmlAttribute(); + Add( attrib ); + attrib->SetName( _name ); + } + return attrib; } -#ifdef TIXML_USE_STL +#ifdef TIXML_USE_STL std::istream& operator>> (std::istream & in, TiXmlNode & base) { - TIXML_STRING tag; - tag.reserve( 8 * 1000 ); - base.StreamIn( &in, &tag ); + TIXML_STRING tag; + tag.reserve( 8 * 1000 ); + base.StreamIn( &in, &tag ); - base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); - return in; + base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); + return in; } #endif -#ifdef TIXML_USE_STL +#ifdef TIXML_USE_STL std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) { - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out << printer.Str(); + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out << printer.Str(); - return out; + return out; } std::string& operator<< (std::string& out, const TiXmlNode& base ) { - TiXmlPrinter printer; - printer.SetStreamPrinting(); - base.Accept( &printer ); - out.append( printer.Str() ); + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out.append( printer.Str() ); - return out; + return out; } #endif TiXmlHandle TiXmlHandle::FirstChild() const { - if ( node ) - { - TiXmlNode* child = node->FirstChild(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); + if ( node ) { + TiXmlNode* child = node->FirstChild(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const { - if ( node ) - { - TiXmlNode* child = node->FirstChild( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); + if ( node ) { + TiXmlNode* child = node->FirstChild( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::FirstChildElement() const { - if ( node ) - { - TiXmlElement* child = node->FirstChildElement(); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); + if ( node ) { + TiXmlElement* child = node->FirstChildElement(); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const { - if ( node ) - { - TiXmlElement* child = node->FirstChildElement( value ); - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); + if ( node ) { + TiXmlElement* child = node->FirstChildElement( value ); + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::Child( int count ) const { - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild(); - for ( i=0; - child && i<count; - child = child->NextSibling(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); + if ( node ) { + int i; + TiXmlNode* child = node->FirstChild(); + for ( i=0; + child && i<count; + child = child->NextSibling(), ++i ) { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const { - if ( node ) - { - int i; - TiXmlNode* child = node->FirstChild( value ); - for ( i=0; - child && i<count; - child = child->NextSibling( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); + if ( node ) { + int i; + TiXmlNode* child = node->FirstChild( value ); + for ( i=0; + child && i<count; + child = child->NextSibling( value ), ++i ) { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::ChildElement( int count ) const { - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement(); - for ( i=0; - child && i<count; - child = child->NextSiblingElement(), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); + if ( node ) { + int i; + TiXmlElement* child = node->FirstChildElement(); + for ( i=0; + child && i<count; + child = child->NextSiblingElement(), ++i ) { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const { - if ( node ) - { - int i; - TiXmlElement* child = node->FirstChildElement( value ); - for ( i=0; - child && i<count; - child = child->NextSiblingElement( value ), ++i ) - { - // nothing - } - if ( child ) - return TiXmlHandle( child ); - } - return TiXmlHandle( 0 ); + if ( node ) { + int i; + TiXmlElement* child = node->FirstChildElement( value ); + for ( i=0; + child && i<count; + child = child->NextSiblingElement( value ), ++i ) { + // nothing + } + if ( child ) + return TiXmlHandle( child ); + } + return TiXmlHandle( 0 ); } bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) { - return true; + return true; } bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) { - return true; + return true; } bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) { - DoIndent(); - buffer += "<"; - buffer += element.Value(); - - for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) - { - buffer += " "; - attrib->Print( 0, 0, &buffer ); - } - - if ( !element.FirstChild() ) - { - buffer += " />"; - DoLineBreak(); - } - else - { - buffer += ">"; - if ( element.FirstChild()->ToText() - && element.LastChild() == element.FirstChild() - && element.FirstChild()->ToText()->CDATA() == false ) - { - simpleTextPrint = true; - // no DoLineBreak()! - } - else - { - DoLineBreak(); - } - } - ++depth; - return true; + DoIndent(); + buffer += "<"; + buffer += element.Value(); + + for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) { + buffer += " "; + attrib->Print( 0, 0, &buffer ); + } + + if ( !element.FirstChild() ) { + buffer += " />"; + DoLineBreak(); + } else { + buffer += ">"; + if ( element.FirstChild()->ToText() + && element.LastChild() == element.FirstChild() + && element.FirstChild()->ToText()->CDATA() == false ) { + simpleTextPrint = true; + // no DoLineBreak()! + } else { + DoLineBreak(); + } + } + ++depth; + return true; } bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) { - --depth; - if ( !element.FirstChild() ) - { - // nothing. - } - else - { - if ( simpleTextPrint ) - { - simpleTextPrint = false; - } - else - { - DoIndent(); - } - buffer += "</"; - buffer += element.Value(); - buffer += ">"; - DoLineBreak(); - } - return true; + --depth; + if ( !element.FirstChild() ) { + // nothing. + } else { + if ( simpleTextPrint ) { + simpleTextPrint = false; + } else { + DoIndent(); + } + buffer += "</"; + buffer += element.Value(); + buffer += ">"; + DoLineBreak(); + } + return true; } bool TiXmlPrinter::Visit( const TiXmlText& text ) { - if ( text.CDATA() ) - { - DoIndent(); - buffer += "<![CDATA["; - buffer += text.Value(); - buffer += "]]>"; - DoLineBreak(); - } - else if ( simpleTextPrint ) - { - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - } - else - { - DoIndent(); - TIXML_STRING str; - TiXmlBase::EncodeString( text.ValueTStr(), &str ); - buffer += str; - DoLineBreak(); - } - return true; + if ( text.CDATA() ) { + DoIndent(); + buffer += "<![CDATA["; + buffer += text.Value(); + buffer += "]]>"; + DoLineBreak(); + } else if ( simpleTextPrint ) { + TIXML_STRING str; + TiXmlBase::EncodeString( text.ValueTStr(), &str ); + buffer += str; + } else { + DoIndent(); + TIXML_STRING str; + TiXmlBase::EncodeString( text.ValueTStr(), &str ); + buffer += str; + DoLineBreak(); + } + return true; } bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) { - DoIndent(); - declaration.Print( 0, 0, &buffer ); - DoLineBreak(); - return true; + DoIndent(); + declaration.Print( 0, 0, &buffer ); + DoLineBreak(); + return true; } bool TiXmlPrinter::Visit( const TiXmlComment& comment ) { - DoIndent(); - buffer += "<!--"; - buffer += comment.Value(); - buffer += "-->"; - DoLineBreak(); - return true; + DoIndent(); + buffer += "<!--"; + buffer += comment.Value(); + buffer += "-->"; + DoLineBreak(); + return true; } bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) { - DoIndent(); - buffer += "<"; - buffer += unknown.Value(); - buffer += ">"; - DoLineBreak(); - return true; + DoIndent(); + buffer += "<"; + buffer += unknown.Value(); + buffer += ">"; + DoLineBreak(); + return true; } diff --git a/tinyxml/tinyxml.h b/tinyxml/tinyxml.h index cae887139b2e80a9f535c6d17aa056f0fcd7ae3c..22ea745035f86b57c0d69af60033e66fc4f0af6d 100644 --- a/tinyxml/tinyxml.h +++ b/tinyxml/tinyxml.h @@ -80,7 +80,7 @@ #define TIXML_SNPRINTF snprintf #define TIXML_SSCANF sscanf #endif -#endif +#endif class TiXmlDocument; class TiXmlElement; @@ -95,16 +95,19 @@ const int TIXML_MAJOR_VERSION = 2; const int TIXML_MINOR_VERSION = 6; const int TIXML_PATCH_VERSION = 2; -/* Internal structure for tracking location of items +/* Internal structure for tracking location of items in the XML file. */ -struct TiXmlCursor -{ - TiXmlCursor() { Clear(); } - void Clear() { row = col = -1; } - - int row; // 0 based. - int col; // 0 based. +struct TiXmlCursor { + TiXmlCursor() { + Clear(); + } + void Clear() { + row = col = -1; + } + + int row; // 0 based. + int col; // 0 based. }; @@ -118,7 +121,7 @@ struct TiXmlCursor If you return 'true' from a Visit method, recursive parsing will continue. If you return false, <b>no children of this node or its sibilings</b> will be Visited. - All flavors of Visit methods have a default implementation that returns 'true' (continue + All flavors of Visit methods have a default implementation that returns 'true' (continue visiting). You need to only override methods that are interesting to you. Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. @@ -127,47 +130,60 @@ struct TiXmlCursor @sa TiXmlNode::Accept() */ -class TiXmlVisitor -{ - public: - virtual ~TiXmlVisitor() {} - - /// Visit a document. - virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } - /// Visit a document. - virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } - - /// Visit an element. - virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } - /// Visit an element. - virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } - - /// Visit a declaration - virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } - /// Visit a text node - virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } - /// Visit a comment node - virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } - /// Visit an unknown node - virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } +class TiXmlVisitor { +public: + virtual ~TiXmlVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { + return true; + } + /// Visit a document. + virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { + return true; + } + + /// Visit an element. + virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { + return true; + } + /// Visit an element. + virtual bool VisitExit( const TiXmlElement& /*element*/ ) { + return true; + } + + /// Visit a declaration + virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { + return true; + } + /// Visit a text node + virtual bool Visit( const TiXmlText& /*text*/ ) { + return true; + } + /// Visit a comment node + virtual bool Visit( const TiXmlComment& /*comment*/ ) { + return true; + } + /// Visit an unknown node + virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { + return true; + } }; // Only used by Attribute::Query functions -enum - { - TIXML_SUCCESS, - TIXML_NO_ATTRIBUTE, - TIXML_WRONG_TYPE - }; +enum { + TIXML_SUCCESS, + TIXML_NO_ATTRIBUTE, + TIXML_WRONG_TYPE +}; // Used by the parsing routines. -enum TiXmlEncoding - { - TIXML_ENCODING_UNKNOWN, - TIXML_ENCODING_UTF8, - TIXML_ENCODING_LEGACY - }; +enum TiXmlEncoding { + TIXML_ENCODING_UNKNOWN, + TIXML_ENCODING_UTF8, + TIXML_ENCODING_LEGACY +}; const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; @@ -193,226 +209,221 @@ const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; A Decleration contains: Attributes (not on tree) @endverbatim */ -class TiXmlBase -{ - friend class TiXmlNode; - friend class TiXmlElement; - friend class TiXmlDocument; - - public: - TiXmlBase() : userData(0) {} - virtual ~TiXmlBase() {} - - /** All TinyXml classes can print themselves to a filestream - or the string class (TiXmlString in non-STL mode, std::string - in STL mode.) Either or both cfile and str can be null. - - This is a formatted print, and will insert - tabs and newlines. - - (For an unformatted stream, use the << operator.) - */ - virtual void Print( FILE* cfile, int depth ) const = 0; - - /** The world does not agree on whether white space should be kept or - not. In order to make everyone happy, these global, static functions - are provided to set whether or not TinyXml will condense all white space - into a single space or not. The default is to condense. Note changing this - value is not thread safe. - */ - static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } - - /// Return the current white space setting. - static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } - - /** Return the position, in the original source file, of this node or attribute. - The row and column are 1-based. (That is the first row and first column is - 1,1). If the returns values are 0 or less, then the parser does not have - a row and column value. - - Generally, the row and column value will be set when the TiXmlDocument::Load(), - TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set - when the DOM was created from operator>>. - - The values reflect the initial load. Once the DOM is modified programmatically - (by adding or changing nodes and attributes) the new values will NOT update to - reflect changes in the document. - - There is a minor performance cost to computing the row and column. Computation - can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. - - @sa TiXmlDocument::SetTabSize() - */ - int Row() const { return location.row + 1; } - int Column() const { return location.col + 1; } ///< See Row() - - void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. - void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. - const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. - - // Table that returs, for a given lead byte, the total number of bytes - // in the UTF-8 sequence. - static const int utf8ByteTable[256]; - - virtual const char* Parse( const char* p, - TiXmlParsingData* data, - TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; - - /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, - or they will be transformed into entities! - */ - static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); - - enum - { - TIXML_NO_ERROR = 0, - TIXML_ERROR, - TIXML_ERROR_OPENING_FILE, - TIXML_ERROR_PARSING_ELEMENT, - TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, - TIXML_ERROR_READING_ELEMENT_VALUE, - TIXML_ERROR_READING_ATTRIBUTES, - TIXML_ERROR_PARSING_EMPTY, - TIXML_ERROR_READING_END_TAG, - TIXML_ERROR_PARSING_UNKNOWN, - TIXML_ERROR_PARSING_COMMENT, - TIXML_ERROR_PARSING_DECLARATION, - TIXML_ERROR_DOCUMENT_EMPTY, - TIXML_ERROR_EMBEDDED_NULL, - TIXML_ERROR_PARSING_CDATA, - TIXML_ERROR_DOCUMENT_TOP_ONLY, - - TIXML_ERROR_STRING_COUNT - }; - - protected: - - static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); - - inline static bool IsWhiteSpace( char c ) - { - return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); - } - inline static bool IsWhiteSpace( int c ) - { - if ( c < 256 ) - return IsWhiteSpace( (char) c ); - return false; // Again, only truly correct for English/Latin...but usually works. - } +class TiXmlBase { + friend class TiXmlNode; + friend class TiXmlElement; + friend class TiXmlDocument; + +public: + TiXmlBase() : userData(0) {} + virtual ~TiXmlBase() {} + + /** All TinyXml classes can print themselves to a filestream + or the string class (TiXmlString in non-STL mode, std::string + in STL mode.) Either or both cfile and str can be null. + + This is a formatted print, and will insert + tabs and newlines. + + (For an unformatted stream, use the << operator.) + */ + virtual void Print( FILE* cfile, int depth ) const = 0; + + /** The world does not agree on whether white space should be kept or + not. In order to make everyone happy, these global, static functions + are provided to set whether or not TinyXml will condense all white space + into a single space or not. The default is to condense. Note changing this + value is not thread safe. + */ + static void SetCondenseWhiteSpace( bool condense ) { + condenseWhiteSpace = condense; + } + + /// Return the current white space setting. + static bool IsWhiteSpaceCondensed() { + return condenseWhiteSpace; + } + + /** Return the position, in the original source file, of this node or attribute. + The row and column are 1-based. (That is the first row and first column is + 1,1). If the returns values are 0 or less, then the parser does not have + a row and column value. + + Generally, the row and column value will be set when the TiXmlDocument::Load(), + TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set + when the DOM was created from operator>>. + + The values reflect the initial load. Once the DOM is modified programmatically + (by adding or changing nodes and attributes) the new values will NOT update to + reflect changes in the document. + + There is a minor performance cost to computing the row and column. Computation + can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. + + @sa TiXmlDocument::SetTabSize() + */ + int Row() const { + return location.row + 1; + } + int Column() const { + return location.col + 1; ///< See Row() + } + + void SetUserData( void* user ) { + userData = user; ///< Set a pointer to arbitrary user data. + } + void* GetUserData() { + return userData; ///< Get a pointer to arbitrary user data. + } + const void* GetUserData() const { + return userData; ///< Get a pointer to arbitrary user data. + } + + // Table that returs, for a given lead byte, the total number of bytes + // in the UTF-8 sequence. + static const int utf8ByteTable[256]; + + virtual const char* Parse( const char* p, + TiXmlParsingData* data, + TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; + + /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, + or they will be transformed into entities! + */ + static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); + + enum { + TIXML_NO_ERROR = 0, + TIXML_ERROR, + TIXML_ERROR_OPENING_FILE, + TIXML_ERROR_PARSING_ELEMENT, + TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, + TIXML_ERROR_READING_ELEMENT_VALUE, + TIXML_ERROR_READING_ATTRIBUTES, + TIXML_ERROR_PARSING_EMPTY, + TIXML_ERROR_READING_END_TAG, + TIXML_ERROR_PARSING_UNKNOWN, + TIXML_ERROR_PARSING_COMMENT, + TIXML_ERROR_PARSING_DECLARATION, + TIXML_ERROR_DOCUMENT_EMPTY, + TIXML_ERROR_EMBEDDED_NULL, + TIXML_ERROR_PARSING_CDATA, + TIXML_ERROR_DOCUMENT_TOP_ONLY, + + TIXML_ERROR_STRING_COUNT + }; + +protected: + + static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); + + inline static bool IsWhiteSpace( char c ) { + return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); + } + inline static bool IsWhiteSpace( int c ) { + if ( c < 256 ) + return IsWhiteSpace( (char) c ); + return false; // Again, only truly correct for English/Latin...but usually works. + } #ifdef TIXML_USE_STL - static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); - static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); + static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); + static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); #endif - /* Reads an XML name into the string provided. Returns - a pointer just past the last character of the name, - or 0 if the function has an error. - */ - static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); - - /* Reads text. Returns a pointer past the given end tag. - Wickedly complex options, but it keeps the (sensitive) code in one place. - */ - static const char* ReadText( const char* in, // where to start - TIXML_STRING* text, // the string read - bool ignoreWhiteSpace, // whether to keep the white space - const char* endTag, // what ends this text - bool ignoreCase, // whether to ignore case in the end tag - TiXmlEncoding encoding ); // the current encoding - - // If an entity has been found, transform it into a character. - static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); - - // Get a character, while interpreting entities. - // The length can be from 0 to 4 bytes. - inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) - { - assert( p ); - if ( encoding == TIXML_ENCODING_UTF8 ) - { - *length = utf8ByteTable[ *((const unsigned char*)p) ]; - assert( *length >= 0 && *length < 5 ); - } - else - { - *length = 1; - } - - if ( *length == 1 ) - { - if ( *p == '&' ) - return GetEntity( p, _value, length, encoding ); - *_value = *p; - return p+1; - } - else if ( *length ) - { - //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), - // and the null terminator isn't needed - for( int i=0; p[i] && i<*length; ++i ) { - _value[i] = p[i]; - } - return p + (*length); - } - else - { - // Not valid text. - return 0; - } - } - - // Return true if the next characters in the stream are any of the endTag sequences. - // Ignore case only works for english, and should only be relied on when comparing - // to English words: StringEqual( p, "version", true ) is fine. - static bool StringEqual( const char* p, - const char* endTag, - bool ignoreCase, - TiXmlEncoding encoding ); - - static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; - - TiXmlCursor location; - - /// Field containing a generic user pointer - void* userData; - - // None of these methods are reliable for any language except English. - // Good for approximation, not great for accuracy. - static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); - static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); - inline static int ToLower( int v, TiXmlEncoding encoding ) - { - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( v < 128 ) return tolower( v ); - return v; - } - else - { - return tolower( v ); - } - } - static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); - - private: - TiXmlBase( const TiXmlBase& ); // not implemented. - void operator=( const TiXmlBase& base ); // not allowed. - - struct Entity - { - const char* str; - unsigned int strLength; - char chr; - }; - enum - { - NUM_ENTITY = 5, - MAX_ENTITY_LENGTH = 6 - - }; - static Entity entity[ NUM_ENTITY ]; - static bool condenseWhiteSpace; + /* Reads an XML name into the string provided. Returns + a pointer just past the last character of the name, + or 0 if the function has an error. + */ + static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); + + /* Reads text. Returns a pointer past the given end tag. + Wickedly complex options, but it keeps the (sensitive) code in one place. + */ + static const char* ReadText( const char* in, // where to start + TIXML_STRING* text, // the string read + bool ignoreWhiteSpace, // whether to keep the white space + const char* endTag, // what ends this text + bool ignoreCase, // whether to ignore case in the end tag + TiXmlEncoding encoding ); // the current encoding + + // If an entity has been found, transform it into a character. + static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); + + // Get a character, while interpreting entities. + // The length can be from 0 to 4 bytes. + inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) { + assert( p ); + if ( encoding == TIXML_ENCODING_UTF8 ) { + *length = utf8ByteTable[ *((const unsigned char*)p) ]; + assert( *length >= 0 && *length < 5 ); + } else { + *length = 1; + } + + if ( *length == 1 ) { + if ( *p == '&' ) + return GetEntity( p, _value, length, encoding ); + *_value = *p; + return p+1; + } else if ( *length ) { + //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), + // and the null terminator isn't needed + for( int i=0; p[i] && i<*length; ++i ) { + _value[i] = p[i]; + } + return p + (*length); + } else { + // Not valid text. + return 0; + } + } + + // Return true if the next characters in the stream are any of the endTag sequences. + // Ignore case only works for english, and should only be relied on when comparing + // to English words: StringEqual( p, "version", true ) is fine. + static bool StringEqual( const char* p, + const char* endTag, + bool ignoreCase, + TiXmlEncoding encoding ); + + static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; + + TiXmlCursor location; + + /// Field containing a generic user pointer + void* userData; + + // None of these methods are reliable for any language except English. + // Good for approximation, not great for accuracy. + static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); + static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); + inline static int ToLower( int v, TiXmlEncoding encoding ) { + if ( encoding == TIXML_ENCODING_UTF8 ) { + if ( v < 128 ) return tolower( v ); + return v; + } else { + return tolower( v ); + } + } + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); + +private: + TiXmlBase( const TiXmlBase& ); // not implemented. + void operator=( const TiXmlBase& base ); // not allowed. + + struct Entity { + const char* str; + unsigned int strLength; + char chr; + }; + enum { + NUM_ENTITY = 5, + MAX_ENTITY_LENGTH = 6 + + }; + static Entity entity[ NUM_ENTITY ]; + static bool condenseWhiteSpace; }; @@ -422,352 +433,436 @@ class TiXmlBase in a document, or stand on its own. The type of a TiXmlNode can be queried, and it can be cast to its more defined type. */ -class TiXmlNode : public TiXmlBase -{ - friend class TiXmlDocument; - friend class TiXmlElement; - - public: -#ifdef TIXML_USE_STL - - /** An input stream operator, for every class. Tolerant of newlines and - formatting, but doesn't expect them. - */ - friend std::istream& operator >> (std::istream& in, TiXmlNode& base); - - /** An output stream operator, for every class. Note that this outputs - without any newlines or formatting, as opposed to Print(), which - includes tabs and new lines. - - The operator<< and operator>> are not completely symmetric. Writing - a node to a stream is very well defined. You'll get a nice stream - of output, without any extra whitespace or newlines. - - But reading is not as well defined. (As it always is.) If you create - a TiXmlElement (for example) and read that from an input stream, - the text needs to define an element or junk will result. This is - true of all input streams, but it's worth keeping in mind. - - A TiXmlDocument will read nodes until it reads a root element, and - all the children of that root element. - */ - friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); - - /// Appends the XML node or attribute to a std::string. - friend std::string& operator<< (std::string& out, const TiXmlNode& base ); +class TiXmlNode : public TiXmlBase { + friend class TiXmlDocument; + friend class TiXmlElement; + +public: +#ifdef TIXML_USE_STL + + /** An input stream operator, for every class. Tolerant of newlines and + formatting, but doesn't expect them. + */ + friend std::istream& operator >> (std::istream& in, TiXmlNode& base); + + /** An output stream operator, for every class. Note that this outputs + without any newlines or formatting, as opposed to Print(), which + includes tabs and new lines. + + The operator<< and operator>> are not completely symmetric. Writing + a node to a stream is very well defined. You'll get a nice stream + of output, without any extra whitespace or newlines. + + But reading is not as well defined. (As it always is.) If you create + a TiXmlElement (for example) and read that from an input stream, + the text needs to define an element or junk will result. This is + true of all input streams, but it's worth keeping in mind. + + A TiXmlDocument will read nodes until it reads a root element, and + all the children of that root element. + */ + friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); + + /// Appends the XML node or attribute to a std::string. + friend std::string& operator<< (std::string& out, const TiXmlNode& base ); #endif - /** The types of XML nodes supported by TinyXml. (All the - unsupported types are picked up by UNKNOWN.) - */ - enum NodeType - { - TINYXML_DOCUMENT, - TINYXML_ELEMENT, - TINYXML_COMMENT, - TINYXML_UNKNOWN, - TINYXML_TEXT, - TINYXML_DECLARATION, - TINYXML_TYPECOUNT - }; - - virtual ~TiXmlNode(); - - /** The meaning of 'value' changes for the specific type of - TiXmlNode. - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - - The subclasses will wrap this function. - */ - const char *Value() const { return value.c_str (); } + /** The types of XML nodes supported by TinyXml. (All the + unsupported types are picked up by UNKNOWN.) + */ + enum NodeType { + TINYXML_DOCUMENT, + TINYXML_ELEMENT, + TINYXML_COMMENT, + TINYXML_UNKNOWN, + TINYXML_TEXT, + TINYXML_DECLARATION, + TINYXML_TYPECOUNT + }; + + virtual ~TiXmlNode(); + + /** The meaning of 'value' changes for the specific type of + TiXmlNode. + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + + The subclasses will wrap this function. + */ + const char *Value() const { + return value.c_str (); + } #ifdef TIXML_USE_STL - /** Return Value() as a std::string. If you only use STL, - this is more efficient than calling Value(). - Only available in STL mode. - */ - const std::string& ValueStr() const { return value; } + /** Return Value() as a std::string. If you only use STL, + this is more efficient than calling Value(). + Only available in STL mode. + */ + const std::string& ValueStr() const { + return value; + } #endif - const TIXML_STRING& ValueTStr() const { return value; } - - /** Changes the value of the node. Defined as: - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - */ - void SetValue(const char * _value) { value = _value;} + const TIXML_STRING& ValueTStr() const { + return value; + } + + /** Changes the value of the node. Defined as: + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + */ + void SetValue(const char * _value) { + value = _value; + } #ifdef TIXML_USE_STL - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } + /// STL std::string form. + void SetValue( const std::string& _value ) { + value = _value; + } #endif - /// Delete all the children of this node. Does not affect 'this'. - void Clear(); - - /// One step up the DOM. - TiXmlNode* Parent() { return parent; } - const TiXmlNode* Parent() const { return parent; } - - const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. - TiXmlNode* FirstChild() { return firstChild; } - const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. - /// The first child of this node with the matching 'value'. Will be null if none found. - TiXmlNode* FirstChild( const char * _value ) { - // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) - // call the method, cast the return back to non-const. - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); - } - const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. - TiXmlNode* LastChild() { return lastChild; } - - const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. - TiXmlNode* LastChild( const char * _value ) { - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); - } + /// Delete all the children of this node. Does not affect 'this'. + void Clear(); + + /// One step up the DOM. + TiXmlNode* Parent() { + return parent; + } + const TiXmlNode* Parent() const { + return parent; + } + + const TiXmlNode* FirstChild() const { + return firstChild; ///< The first child of this node. Will be null if there are no children. + } + TiXmlNode* FirstChild() { + return firstChild; + } + const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. + /// The first child of this node with the matching 'value'. Will be null if none found. + TiXmlNode* FirstChild( const char * _value ) { + // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) + // call the method, cast the return back to non-const. + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); + } + const TiXmlNode* LastChild() const { + return lastChild; /// The last child of this node. Will be null if there are no children. + } + TiXmlNode* LastChild() { + return lastChild; + } + + const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. + TiXmlNode* LastChild( const char * _value ) { + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); + } #ifdef TIXML_USE_STL - const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* FirstChild( const std::string& _value ) const { + return FirstChild (_value.c_str ()); ///< STL std::string form. + } + TiXmlNode* FirstChild( const std::string& _value ) { + return FirstChild (_value.c_str ()); ///< STL std::string form. + } + const TiXmlNode* LastChild( const std::string& _value ) const { + return LastChild (_value.c_str ()); ///< STL std::string form. + } + TiXmlNode* LastChild( const std::string& _value ) { + return LastChild (_value.c_str ()); ///< STL std::string form. + } #endif - /** An alternate way to walk the children of a node. - One way to iterate over nodes is: - @verbatim - for( child = parent->FirstChild(); child; child = child->NextSibling() ) - @endverbatim - - IterateChildren does the same thing with the syntax: - @verbatim - child = 0; - while( child = parent->IterateChildren( child ) ) - @endverbatim - - IterateChildren takes the previous child as input and finds - the next one. If the previous child is null, it returns the - first. IterateChildren will return null when done. - */ - const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); - } - - /// This flavor of IterateChildren searches for children with a particular 'value' - const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); - } + /** An alternate way to walk the children of a node. + One way to iterate over nodes is: + @verbatim + for( child = parent->FirstChild(); child; child = child->NextSibling() ) + @endverbatim + + IterateChildren does the same thing with the syntax: + @verbatim + child = 0; + while( child = parent->IterateChildren( child ) ) + @endverbatim + + IterateChildren takes the previous child as input and finds + the next one. If the previous child is null, it returns the + first. IterateChildren will return null when done. + */ + const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); + } + + /// This flavor of IterateChildren searches for children with a particular 'value' + const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); + } #ifdef TIXML_USE_STL - const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { + return IterateChildren (_value.c_str (), previous); ///< STL std::string form. + } + TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { + return IterateChildren (_value.c_str (), previous); ///< STL std::string form. + } #endif - /** Add a new node related to this. Adds a child past the LastChild. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); + /** Add a new node related to this. Adds a child past the LastChild. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); - /** Add a new node related to this. Adds a child past the LastChild. + /** Add a new node related to this. Adds a child past the LastChild. - NOTE: the node to be added is passed by pointer, and will be - henceforth owned (and deleted) by tinyXml. This method is efficient - and avoids an extra copy, but should be used with care as it - uses a different memory model than the other insert functions. + NOTE: the node to be added is passed by pointer, and will be + henceforth owned (and deleted) by tinyXml. This method is efficient + and avoids an extra copy, but should be used with care as it + uses a different memory model than the other insert functions. - @sa InsertEndChild - */ - TiXmlNode* LinkEndChild( TiXmlNode* addThis ); + @sa InsertEndChild + */ + TiXmlNode* LinkEndChild( TiXmlNode* addThis ); - /** Add a new node related to this. Adds a child before the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); + /** Add a new node related to this. Adds a child before the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); - /** Add a new node related to this. Adds a child after the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); + /** Add a new node related to this. Adds a child after the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); - /** Replace a child of this node. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); + /** Replace a child of this node. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); - /// Delete a child of this node. - bool RemoveChild( TiXmlNode* removeThis ); + /// Delete a child of this node. + bool RemoveChild( TiXmlNode* removeThis ); - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling() const { return prev; } - TiXmlNode* PreviousSibling() { return prev; } + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling() const { + return prev; + } + TiXmlNode* PreviousSibling() { + return prev; + } - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling( const char * ) const; - TiXmlNode* PreviousSibling( const char *_prev ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); - } + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling( const char * ) const; + TiXmlNode* PreviousSibling( const char *_prev ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); + } #ifdef TIXML_USE_STL - const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* PreviousSibling( const std::string& _value ) const { + return PreviousSibling (_value.c_str ()); ///< STL std::string form. + } + TiXmlNode* PreviousSibling( const std::string& _value ) { + return PreviousSibling (_value.c_str ()); ///< STL std::string form. + } + const TiXmlNode* NextSibling( const std::string& _value) const { + return NextSibling (_value.c_str ()); ///< STL std::string form. + } + TiXmlNode* NextSibling( const std::string& _value) { + return NextSibling (_value.c_str ()); ///< STL std::string form. + } #endif - /// Navigate to a sibling node. - const TiXmlNode* NextSibling() const { return next; } - TiXmlNode* NextSibling() { return next; } - - /// Navigate to a sibling node with the given 'value'. - const TiXmlNode* NextSibling( const char * ) const; - TiXmlNode* NextSibling( const char* _next ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement() const; - TiXmlElement* NextSiblingElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement( const char * ) const; - TiXmlElement* NextSiblingElement( const char *_next ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); - } + /// Navigate to a sibling node. + const TiXmlNode* NextSibling() const { + return next; + } + TiXmlNode* NextSibling() { + return next; + } + + /// Navigate to a sibling node with the given 'value'. + const TiXmlNode* NextSibling( const char * ) const; + TiXmlNode* NextSibling( const char* _next ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement() const; + TiXmlElement* NextSiblingElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement( const char * ) const; + TiXmlElement* NextSiblingElement( const char *_next ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); + } #ifdef TIXML_USE_STL - const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + const TiXmlElement* NextSiblingElement( const std::string& _value) const { + return NextSiblingElement (_value.c_str ()); ///< STL std::string form. + } + TiXmlElement* NextSiblingElement( const std::string& _value) { + return NextSiblingElement (_value.c_str ()); ///< STL std::string form. + } #endif - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement() const; - TiXmlElement* FirstChildElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); - } + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement() const; + TiXmlElement* FirstChildElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); + } - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement( const char * _value ) const; - TiXmlElement* FirstChildElement( const char * _value ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); - } + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement( const char * _value ) const; + TiXmlElement* FirstChildElement( const char * _value ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); + } #ifdef TIXML_USE_STL - const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + const TiXmlElement* FirstChildElement( const std::string& _value ) const { + return FirstChildElement (_value.c_str ()); ///< STL std::string form. + } + TiXmlElement* FirstChildElement( const std::string& _value ) { + return FirstChildElement (_value.c_str ()); ///< STL std::string form. + } #endif - /** Query the type (as an enumerated value, above) of this node. - The possible types are: TINYXML_DOCUMENT, TINYXML_ELEMENT, TINYXML_COMMENT, - TINYXML_UNKNOWN, TINYXML_TEXT, and TINYXML_DECLARATION. - */ - int Type() const { return type; } - - /** Return a pointer to the Document this node lives in. - Returns null if not in a document. - */ - const TiXmlDocument* GetDocument() const; - TiXmlDocument* GetDocument() { - return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); - } - - /// Returns true if this node has no children. - bool NoChildren() const { return !firstChild; } - - virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - /** Create an exact duplicate of this node and return it. The memory must be deleted - by the caller. - */ - virtual TiXmlNode* Clone() const = 0; - - /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the - XML tree will be conditionally visited and the host will be called back - via the TiXmlVisitor interface. - - This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse - the XML for the callbacks, so the performance of TinyXML is unchanged by using this - interface versus any other.) - - The interface has been based on ideas from: - - - http://www.saxproject.org/ - - http://c2.com/cgi/wiki?HierarchicalVisitorPattern - - Which are both good references for "visiting". - - An example of using Accept(): - @verbatim - TiXmlPrinter printer; - tinyxmlDoc.Accept( &printer ); - const char* xmlcstr = printer.CStr(); - @endverbatim - */ - virtual bool Accept( TiXmlVisitor* visitor ) const = 0; - - protected: - TiXmlNode( NodeType _type ); - - // Copy to the allocated object. Shared functionality between Clone, Copy constructor, - // and the assignment operator. - void CopyTo( TiXmlNode* target ) const; + /** Query the type (as an enumerated value, above) of this node. + The possible types are: TINYXML_DOCUMENT, TINYXML_ELEMENT, TINYXML_COMMENT, + TINYXML_UNKNOWN, TINYXML_TEXT, and TINYXML_DECLARATION. + */ + int Type() const { + return type; + } + + /** Return a pointer to the Document this node lives in. + Returns null if not in a document. + */ + const TiXmlDocument* GetDocument() const; + TiXmlDocument* GetDocument() { + return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); + } + + /// Returns true if this node has no children. + bool NoChildren() const { + return !firstChild; + } + + virtual const TiXmlDocument* ToDocument() const { + return 0; ///< Cast to a more defined type. Will return null if not of the requested type. + } + virtual const TiXmlElement* ToElement() const { + return 0; ///< Cast to a more defined type. Will return null if not of the requested type. + } + virtual const TiXmlComment* ToComment() const { + return 0; ///< Cast to a more defined type. Will return null if not of the requested type. + } + virtual const TiXmlUnknown* ToUnknown() const { + return 0; ///< Cast to a more defined type. Will return null if not of the requested type. + } + virtual const TiXmlText* ToText() const { + return 0; ///< Cast to a more defined type. Will return null if not of the requested type. + } + virtual const TiXmlDeclaration* ToDeclaration() const { + return 0; ///< Cast to a more defined type. Will return null if not of the requested type. + } + + virtual TiXmlDocument* ToDocument() { + return 0; ///< Cast to a more defined type. Will return null if not of the requested type. + } + virtual TiXmlElement* ToElement() { + return 0; ///< Cast to a more defined type. Will return null if not of the requested type. + } + virtual TiXmlComment* ToComment() { + return 0; ///< Cast to a more defined type. Will return null if not of the requested type. + } + virtual TiXmlUnknown* ToUnknown() { + return 0; ///< Cast to a more defined type. Will return null if not of the requested type. + } + virtual TiXmlText* ToText() { + return 0; ///< Cast to a more defined type. Will return null if not of the requested type. + } + virtual TiXmlDeclaration* ToDeclaration() { + return 0; ///< Cast to a more defined type. Will return null if not of the requested type. + } + + /** Create an exact duplicate of this node and return it. The memory must be deleted + by the caller. + */ + virtual TiXmlNode* Clone() const = 0; + + /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the TiXmlVisitor interface. + + This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + TiXmlPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( TiXmlVisitor* visitor ) const = 0; + +protected: + TiXmlNode( NodeType _type ); + + // Copy to the allocated object. Shared functionality between Clone, Copy constructor, + // and the assignment operator. + void CopyTo( TiXmlNode* target ) const; #ifdef TIXML_USE_STL - // The real work of the input operator. - virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; + // The real work of the input operator. + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; #endif - // Figure out what is at *p, and parse it. Returns null if it is not an xml node. - TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); + // Figure out what is at *p, and parse it. Returns null if it is not an xml node. + TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); - TiXmlNode* parent; - NodeType type; + TiXmlNode* parent; + NodeType type; - TiXmlNode* firstChild; - TiXmlNode* lastChild; + TiXmlNode* firstChild; + TiXmlNode* lastChild; - TIXML_STRING value; + TIXML_STRING value; - TiXmlNode* prev; - TiXmlNode* next; + TiXmlNode* prev; + TiXmlNode* next; - private: - TiXmlNode( const TiXmlNode& ); // not implemented. - void operator=( const TiXmlNode& base ); // not allowed. +private: + TiXmlNode( const TiXmlNode& ); // not implemented. + void operator=( const TiXmlNode& base ); // not allowed. }; @@ -778,121 +873,141 @@ class TiXmlNode : public TiXmlBase part of the tinyXML document object model. There are other suggested ways to look at this problem. */ -class TiXmlAttribute : public TiXmlBase -{ - friend class TiXmlAttributeSet; - - public: - /// Construct an empty attribute. - TiXmlAttribute() : TiXmlBase() - { - document = 0; - prev = next = 0; - } +class TiXmlAttribute : public TiXmlBase { + friend class TiXmlAttributeSet; + +public: + /// Construct an empty attribute. + TiXmlAttribute() : TiXmlBase() { + document = 0; + prev = next = 0; + } #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlAttribute( const std::string& _name, const std::string& _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } + /// std::string constructor. + TiXmlAttribute( const std::string& _name, const std::string& _value ) { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } #endif - /// Construct an attribute with a name and value. - TiXmlAttribute( const char * _name, const char * _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - - const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. - const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. + /// Construct an attribute with a name and value. + TiXmlAttribute( const char * _name, const char * _value ) { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + + const char* Name() const { + return name.c_str(); ///< Return the name of this attribute. + } + const char* Value() const { + return value.c_str(); ///< Return the value of this attribute. + } #ifdef TIXML_USE_STL - const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. + const std::string& ValueStr() const { + return value; ///< Return the value of this attribute. + } #endif - int IntValue() const; ///< Return the value of this attribute, converted to an integer. - double DoubleValue() const; ///< Return the value of this attribute, converted to a double. - - // Get the tinyxml string representation - const TIXML_STRING& NameTStr() const { return name; } - - /** QueryIntValue examines the value string. It is an alternative to the - IntValue() method with richer error checking. - If the value is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. - - A specialized but useful call. Note that for success it returns 0, - which is the opposite of almost all other TinyXml calls. - */ - int QueryIntValue( int* _value ) const; - /// QueryDoubleValue examines the value string. See QueryIntValue(). - int QueryDoubleValue( double* _value ) const; - - void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. - void SetValue( const char* _value ) { value = _value; } ///< Set the value. - - void SetIntValue( int _value ); ///< Set the value from an integer. - void SetDoubleValue( double _value ); ///< Set the value from a double. + int IntValue() const; ///< Return the value of this attribute, converted to an integer. + double DoubleValue() const; ///< Return the value of this attribute, converted to a double. + + // Get the tinyxml string representation + const TIXML_STRING& NameTStr() const { + return name; + } + + /** QueryIntValue examines the value string. It is an alternative to the + IntValue() method with richer error checking. + If the value is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. + + A specialized but useful call. Note that for success it returns 0, + which is the opposite of almost all other TinyXml calls. + */ + int QueryIntValue( int* _value ) const; + /// QueryDoubleValue examines the value string. See QueryIntValue(). + int QueryDoubleValue( double* _value ) const; + + void SetName( const char* _name ) { + name = _name; ///< Set the name of this attribute. + } + void SetValue( const char* _value ) { + value = _value; ///< Set the value. + } + + void SetIntValue( int _value ); ///< Set the value from an integer. + void SetDoubleValue( double _value ); ///< Set the value from a double. #ifdef TIXML_USE_STL - /// STL std::string form. - void SetName( const std::string& _name ) { name = _name; } - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } + /// STL std::string form. + void SetName( const std::string& _name ) { + name = _name; + } + /// STL std::string form. + void SetValue( const std::string& _value ) { + value = _value; + } #endif - /// Get the next sibling attribute in the DOM. Returns null at end. - const TiXmlAttribute* Next() const; - TiXmlAttribute* Next() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); - } - - /// Get the previous sibling attribute in the DOM. Returns null at beginning. - const TiXmlAttribute* Previous() const; - TiXmlAttribute* Previous() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); - } - - bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } - bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } - bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } - - /* Attribute parsing starts: first letter of the name - returns: the next char after the value end quote - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - // Prints this Attribute to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - - // [internal use] - // Set the document pointer so the attribute can report errors. - void SetDocument( TiXmlDocument* doc ) { document = doc; } - - private: - TiXmlAttribute( const TiXmlAttribute& ); // not implemented. - void operator=( const TiXmlAttribute& base ); // not allowed. - - TiXmlDocument* document; // A pointer back to a document, for error reporting. - TIXML_STRING name; - TIXML_STRING value; - TiXmlAttribute* prev; - TiXmlAttribute* next; + /// Get the next sibling attribute in the DOM. Returns null at end. + const TiXmlAttribute* Next() const; + TiXmlAttribute* Next() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); + } + + /// Get the previous sibling attribute in the DOM. Returns null at beginning. + const TiXmlAttribute* Previous() const; + TiXmlAttribute* Previous() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); + } + + bool operator==( const TiXmlAttribute& rhs ) const { + return rhs.name == name; + } + bool operator<( const TiXmlAttribute& rhs ) const { + return name < rhs.name; + } + bool operator>( const TiXmlAttribute& rhs ) const { + return name > rhs.name; + } + + /* Attribute parsing starts: first letter of the name + returns: the next char after the value end quote + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + // Prints this Attribute to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + + // [internal use] + // Set the document pointer so the attribute can report errors. + void SetDocument( TiXmlDocument* doc ) { + document = doc; + } + +private: + TiXmlAttribute( const TiXmlAttribute& ); // not implemented. + void operator=( const TiXmlAttribute& base ); // not allowed. + + TiXmlDocument* document; // A pointer back to a document, for error reporting. + TIXML_STRING name; + TIXML_STRING value; + TiXmlAttribute* prev; + TiXmlAttribute* next; }; /* A class used to manage a group of attributes. It is only used internally, both by the ELEMENT and the DECLARATION. - + The set can be changed transparent to the Element and Declaration classes that use it, but NOT transparent to the Attribute which has to implement a next() and previous() method. Which makes @@ -902,36 +1017,43 @@ class TiXmlAttribute : public TiXmlBase - I like circular lists - it demonstrates some independence from the (typical) doubly linked list. */ -class TiXmlAttributeSet -{ - public: - TiXmlAttributeSet(); - ~TiXmlAttributeSet(); - - void Add( TiXmlAttribute* attribute ); - void Remove( TiXmlAttribute* attribute ); - - const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - - TiXmlAttribute* Find( const char* _name ) const; - TiXmlAttribute* FindOrCreate( const char* _name ); +class TiXmlAttributeSet { +public: + TiXmlAttributeSet(); + ~TiXmlAttributeSet(); + + void Add( TiXmlAttribute* attribute ); + void Remove( TiXmlAttribute* attribute ); + + const TiXmlAttribute* First() const { + return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; + } + TiXmlAttribute* First() { + return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; + } + const TiXmlAttribute* Last() const { + return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; + } + TiXmlAttribute* Last() { + return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; + } + + TiXmlAttribute* Find( const char* _name ) const; + TiXmlAttribute* FindOrCreate( const char* _name ); # ifdef TIXML_USE_STL - TiXmlAttribute* Find( const std::string& _name ) const; - TiXmlAttribute* FindOrCreate( const std::string& _name ); + TiXmlAttribute* Find( const std::string& _name ) const; + TiXmlAttribute* FindOrCreate( const std::string& _name ); # endif - private: - //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), - //*ME: this class must be also use a hidden/disabled copy-constructor !!! - TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed - void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) +private: + //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), + //*ME: this class must be also use a hidden/disabled copy-constructor !!! + TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed + void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) - TiXmlAttribute sentinel; + TiXmlAttribute sentinel; }; @@ -939,335 +1061,359 @@ class TiXmlAttributeSet and can contain other elements, text, comments, and unknowns. Elements also contain an arbitrary number of attributes. */ -class TiXmlElement : public TiXmlNode -{ - public: - /// Construct an element. - TiXmlElement (const char * in_value); +class TiXmlElement : public TiXmlNode { +public: + /// Construct an element. + TiXmlElement (const char * in_value); #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlElement( const std::string& _value ); + /// std::string constructor. + TiXmlElement( const std::string& _value ); #endif - TiXmlElement( const TiXmlElement& ); - - TiXmlElement& operator=( const TiXmlElement& base ); - - virtual ~TiXmlElement(); - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - */ - const char* Attribute( const char* name ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an integer, - the integer value will be put in the return 'i', if 'i' - is non-null. - */ - const char* Attribute( const char* name, int* i ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an double, - the double value will be put in the return 'd', if 'd' - is non-null. - */ - const char* Attribute( const char* name, double* d ) const; - - /** QueryIntAttribute examines the attribute - it is an alternative to the - Attribute() method with richer error checking. - If the attribute is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. If the attribute - does not exist, then TIXML_NO_ATTRIBUTE is returned. - */ - int QueryIntAttribute( const char* name, int* _value ) const; - /// QueryUnsignedAttribute examines the attribute - see QueryIntAttribute(). - int QueryUnsignedAttribute( const char* name, unsigned* _value ) const; - /** QueryBoolAttribute examines the attribute - see QueryIntAttribute(). - Note that '1', 'true', or 'yes' are considered true, while '0', 'false' - and 'no' are considered false. - */ - int QueryBoolAttribute( const char* name, bool* _value ) const; - /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). - int QueryDoubleAttribute( const char* name, double* _value ) const; - /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). - int QueryFloatAttribute( const char* name, float* _value ) const { - double d; - int result = QueryDoubleAttribute( name, &d ); - if ( result == TIXML_SUCCESS ) { - *_value = (float)d; - } - return result; - } + TiXmlElement( const TiXmlElement& ); + + TiXmlElement& operator=( const TiXmlElement& base ); + + virtual ~TiXmlElement(); + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + */ + const char* Attribute( const char* name ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an integer, + the integer value will be put in the return 'i', if 'i' + is non-null. + */ + const char* Attribute( const char* name, int* i ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an double, + the double value will be put in the return 'd', if 'd' + is non-null. + */ + const char* Attribute( const char* name, double* d ) const; + + /** QueryIntAttribute examines the attribute - it is an alternative to the + Attribute() method with richer error checking. + If the attribute is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. If the attribute + does not exist, then TIXML_NO_ATTRIBUTE is returned. + */ + int QueryIntAttribute( const char* name, int* _value ) const; + /// QueryUnsignedAttribute examines the attribute - see QueryIntAttribute(). + int QueryUnsignedAttribute( const char* name, unsigned* _value ) const; + /** QueryBoolAttribute examines the attribute - see QueryIntAttribute(). + Note that '1', 'true', or 'yes' are considered true, while '0', 'false' + and 'no' are considered false. + */ + int QueryBoolAttribute( const char* name, bool* _value ) const; + /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). + int QueryDoubleAttribute( const char* name, double* _value ) const; + /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). + int QueryFloatAttribute( const char* name, float* _value ) const { + double d; + int result = QueryDoubleAttribute( name, &d ); + if ( result == TIXML_SUCCESS ) { + *_value = (float)d; + } + return result; + } #ifdef TIXML_USE_STL - /// QueryStringAttribute examines the attribute - see QueryIntAttribute(). - int QueryStringAttribute( const char* name, std::string* _value ) const { - const char* cstr = Attribute( name ); - if ( cstr ) { - *_value = std::string( cstr ); - return TIXML_SUCCESS; - } - return TIXML_NO_ATTRIBUTE; - } - - /** Template form of the attribute query which will try to read the - attribute into the specified type. Very easy, very powerful, but - be careful to make sure to call this with the correct type. - - NOTE: This method doesn't work correctly for 'string' types that contain spaces. - - @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE - */ - template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - std::stringstream sstream( node->ValueStr() ); - sstream >> *outValue; - if ( !sstream.fail() ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; - } - - int QueryValueAttribute( const std::string& name, std::string* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - *outValue = node->ValueStr(); - return TIXML_SUCCESS; - } + /// QueryStringAttribute examines the attribute - see QueryIntAttribute(). + int QueryStringAttribute( const char* name, std::string* _value ) const { + const char* cstr = Attribute( name ); + if ( cstr ) { + *_value = std::string( cstr ); + return TIXML_SUCCESS; + } + return TIXML_NO_ATTRIBUTE; + } + + /** Template form of the attribute query which will try to read the + attribute into the specified type. Very easy, very powerful, but + be careful to make sure to call this with the correct type. + + NOTE: This method doesn't work correctly for 'string' types that contain spaces. + + @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE + */ + template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + std::stringstream sstream( node->ValueStr() ); + sstream >> *outValue; + if ( !sstream.fail() ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; + } + + int QueryValueAttribute( const std::string& name, std::string* outValue ) const { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + *outValue = node->ValueStr(); + return TIXML_SUCCESS; + } #endif - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char* name, const char * _value ); + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char* name, const char * _value ); #ifdef TIXML_USE_STL - const std::string* Attribute( const std::string& name ) const; - const std::string* Attribute( const std::string& name, int* i ) const; - const std::string* Attribute( const std::string& name, double* d ) const; - int QueryIntAttribute( const std::string& name, int* _value ) const; - int QueryDoubleAttribute( const std::string& name, double* _value ) const; - - /// STL std::string form. - void SetAttribute( const std::string& name, const std::string& _value ); - ///< STL std::string form. - void SetAttribute( const std::string& name, int _value ); - ///< STL std::string form. - void SetDoubleAttribute( const std::string& name, double value ); + const std::string* Attribute( const std::string& name ) const; + const std::string* Attribute( const std::string& name, int* i ) const; + const std::string* Attribute( const std::string& name, double* d ) const; + int QueryIntAttribute( const std::string& name, int* _value ) const; + int QueryDoubleAttribute( const std::string& name, double* _value ) const; + + /// STL std::string form. + void SetAttribute( const std::string& name, const std::string& _value ); + ///< STL std::string form. + void SetAttribute( const std::string& name, int _value ); + ///< STL std::string form. + void SetDoubleAttribute( const std::string& name, double value ); #endif - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char * name, int value ); + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char * name, int value ); - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetDoubleAttribute( const char * name, double value ); + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetDoubleAttribute( const char * name, double value ); - /** Deletes an attribute with the given name. - */ - void RemoveAttribute( const char * name ); + /** Deletes an attribute with the given name. + */ + void RemoveAttribute( const char * name ); #ifdef TIXML_USE_STL - void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. + void RemoveAttribute( const std::string& name ) { + RemoveAttribute (name.c_str ()); ///< STL std::string form. + } #endif - const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. - TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } - const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. - TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } - - /** Convenience function for easy access to the text inside an element. Although easy - and concise, GetText() is limited compared to getting the TiXmlText child - and accessing it directly. - - If the first child of 'this' is a TiXmlText, the GetText() - returns the character string of the Text node, else null is returned. - - This is a convenient method for getting the text of simple contained text: - @verbatim - <foo>This is text</foo> - const char* str = fooElement->GetText(); - @endverbatim - - 'str' will be a pointer to "This is text". - - Note that this function can be misleading. If the element foo was created from - this XML: - @verbatim - <foo><b>This is text</b></foo> - @endverbatim - - then the value of str would be null. The first child node isn't a text node, it is - another element. From this XML: - @verbatim - <foo>This is <b>text</b></foo> - @endverbatim - GetText() will return "This is ". - - WARNING: GetText() accesses a child node - don't become confused with the - similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are - safe type casts on the referenced node. - */ - const char* GetText() const; - - /// Creates a new Element and returns it - the returned element is a copy. - virtual TiXmlNode* Clone() const; - // Print the Element to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: next char past '<' - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - - protected: - - void CopyTo( TiXmlElement* target ) const; - void ClearThis(); // like clear, but initializes 'this' object as well - - // Used to be public [internal use] + const TiXmlAttribute* FirstAttribute() const { + return attributeSet.First(); ///< Access the first attribute in this element. + } + TiXmlAttribute* FirstAttribute() { + return attributeSet.First(); + } + const TiXmlAttribute* LastAttribute() const { + return attributeSet.Last(); ///< Access the last attribute in this element. + } + TiXmlAttribute* LastAttribute() { + return attributeSet.Last(); + } + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the TiXmlText child + and accessing it directly. + + If the first child of 'this' is a TiXmlText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + <foo>This is text</foo> + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + <foo><b>This is text</b></foo> + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + <foo>This is <b>text</b></foo> + @endverbatim + GetText() will return "This is ". + + WARNING: GetText() accesses a child node - don't become confused with the + similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are + safe type casts on the referenced node. + */ + const char* GetText() const; + + /// Creates a new Element and returns it - the returned element is a copy. + virtual TiXmlNode* Clone() const; + // Print the Element to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: next char past '<' + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlElement* ToElement() const { + return this; ///< Cast to a more defined type. Will return null not of the requested type. + } + virtual TiXmlElement* ToElement() { + return this; ///< Cast to a more defined type. Will return null not of the requested type. + } + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + + void CopyTo( TiXmlElement* target ) const; + void ClearThis(); // like clear, but initializes 'this' object as well + + // Used to be public [internal use] #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); #endif - /* [internal use] - Reads the "value" of the element -- another element, or text. - This should terminate with the current end tag. - */ - const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - - private: - TiXmlAttributeSet attributeSet; + /* [internal use] + Reads the "value" of the element -- another element, or text. + This should terminate with the current end tag. + */ + const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + +private: + TiXmlAttributeSet attributeSet; }; /** An XML comment. */ -class TiXmlComment : public TiXmlNode -{ - public: - /// Constructs an empty comment. - TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {} - /// Construct a comment from text. - TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) { - SetValue( _value ); - } - TiXmlComment( const TiXmlComment& ); - TiXmlComment& operator=( const TiXmlComment& base ); - - virtual ~TiXmlComment() {} - - /// Returns a copy of this Comment. - virtual TiXmlNode* Clone() const; - // Write this Comment to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: at the ! of the !-- - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - - protected: - void CopyTo( TiXmlComment* target ) const; - - // used to be public +class TiXmlComment : public TiXmlNode { +public: + /// Constructs an empty comment. + TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {} + /// Construct a comment from text. + TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) { + SetValue( _value ); + } + TiXmlComment( const TiXmlComment& ); + TiXmlComment& operator=( const TiXmlComment& base ); + + virtual ~TiXmlComment() {} + + /// Returns a copy of this Comment. + virtual TiXmlNode* Clone() const; + // Write this Comment to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: at the ! of the !-- + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlComment* ToComment() const { + return this; ///< Cast to a more defined type. Will return null not of the requested type. + } + virtual TiXmlComment* ToComment() { + return this; ///< Cast to a more defined type. Will return null not of the requested type. + } + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlComment* target ) const; + + // used to be public #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); #endif - // virtual void StreamOut( TIXML_OSTREAM * out ) const; + // virtual void StreamOut( TIXML_OSTREAM * out ) const; - private: +private: }; -/** XML text. A text node can have 2 ways to output the next. "normal" output +/** XML text. A text node can have 2 ways to output the next. "normal" output and CDATA. It will default to the mode it was parsed from the XML file and - you generally want to leave it alone, but you can change the output mode with + you generally want to leave it alone, but you can change the output mode with SetCDATA() and query it with CDATA(). */ -class TiXmlText : public TiXmlNode -{ - friend class TiXmlElement; - public: - /** Constructor for text element. By default, it is treated as - normal, encoded text. If you want it be output as a CDATA text - element, set the parameter _cdata to 'true' - */ - TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) - { - SetValue( initValue ); - cdata = false; - } - virtual ~TiXmlText() {} +class TiXmlText : public TiXmlNode { + friend class TiXmlElement; +public: + /** Constructor for text element. By default, it is treated as + normal, encoded text. If you want it be output as a CDATA text + element, set the parameter _cdata to 'true' + */ + TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) { + SetValue( initValue ); + cdata = false; + } + virtual ~TiXmlText() {} #ifdef TIXML_USE_STL - /// Constructor. - TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) - { - SetValue( initValue ); - cdata = false; - } + /// Constructor. + TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) { + SetValue( initValue ); + cdata = false; + } #endif - TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { copy.CopyTo( this ); } - TiXmlText& operator=( const TiXmlText& base ) { base.CopyTo( this ); return *this; } - - // Write this text object to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /// Queries whether this represents text using a CDATA section. - bool CDATA() const { return cdata; } - /// Turns on or off a CDATA representation of text. - void SetCDATA( bool _cdata ) { cdata = _cdata; } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - - protected : - /// [internal use] Creates a new Element and returns it. - virtual TiXmlNode* Clone() const; - void CopyTo( TiXmlText* target ) const; - - bool Blank() const; // returns true if all white space and new lines - // [internal use] + TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { + copy.CopyTo( this ); + } + TiXmlText& operator=( const TiXmlText& base ) { + base.CopyTo( this ); + return *this; + } + + // Write this text object to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /// Queries whether this represents text using a CDATA section. + bool CDATA() const { + return cdata; + } + /// Turns on or off a CDATA representation of text. + void SetCDATA( bool _cdata ) { + cdata = _cdata; + } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlText* ToText() const { + return this; ///< Cast to a more defined type. Will return null not of the requested type. + } + virtual TiXmlText* ToText() { + return this; ///< Cast to a more defined type. Will return null not of the requested type. + } + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + /// [internal use] Creates a new Element and returns it. + virtual TiXmlNode* Clone() const; + void CopyTo( TiXmlText* target ) const; + + bool Blank() const; // returns true if all white space and new lines + // [internal use] #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); #endif - private: - bool cdata; // true if this should be input and output as a CDATA style text element +private: + bool cdata; // true if this should be input and output as a CDATA style text element }; @@ -1284,65 +1430,74 @@ class TiXmlText : public TiXmlNode handled as special cases, not generic attributes, simply because there can only be at most 3 and they are always the same. */ -class TiXmlDeclaration : public TiXmlNode -{ - public: - /// Construct an empty declaration. - TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {} +class TiXmlDeclaration : public TiXmlNode { +public: + /// Construct an empty declaration. + TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {} #ifdef TIXML_USE_STL - /// Constructor. - TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ); + /// Constructor. + TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ); #endif - /// Construct. - TiXmlDeclaration( const char* _version, - const char* _encoding, - const char* _standalone ); - - TiXmlDeclaration( const TiXmlDeclaration& copy ); - TiXmlDeclaration& operator=( const TiXmlDeclaration& copy ); - - virtual ~TiXmlDeclaration() {} - - /// Version. Will return an empty string if none was found. - const char *Version() const { return version.c_str (); } - /// Encoding. Will return an empty string if none was found. - const char *Encoding() const { return encoding.c_str (); } - /// Is this a standalone document? - const char *Standalone() const { return standalone.c_str (); } - - /// Creates a copy of this Declaration and returns it. - virtual TiXmlNode* Clone() const; - // Print this declaration to a FILE stream. - virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; - - protected: - void CopyTo( TiXmlDeclaration* target ) const; - // used to be public + /// Construct. + TiXmlDeclaration( const char* _version, + const char* _encoding, + const char* _standalone ); + + TiXmlDeclaration( const TiXmlDeclaration& copy ); + TiXmlDeclaration& operator=( const TiXmlDeclaration& copy ); + + virtual ~TiXmlDeclaration() {} + + /// Version. Will return an empty string if none was found. + const char *Version() const { + return version.c_str (); + } + /// Encoding. Will return an empty string if none was found. + const char *Encoding() const { + return encoding.c_str (); + } + /// Is this a standalone document? + const char *Standalone() const { + return standalone.c_str (); + } + + /// Creates a copy of this Declaration and returns it. + virtual TiXmlNode* Clone() const; + // Print this declaration to a FILE stream. + virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlDeclaration* ToDeclaration() const { + return this; ///< Cast to a more defined type. Will return null not of the requested type. + } + virtual TiXmlDeclaration* ToDeclaration() { + return this; ///< Cast to a more defined type. Will return null not of the requested type. + } + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlDeclaration* target ) const; + // used to be public #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); #endif - private: +private: - TIXML_STRING version; - TIXML_STRING encoding; - TIXML_STRING standalone; + TIXML_STRING version; + TIXML_STRING encoding; + TIXML_STRING standalone; }; @@ -1353,37 +1508,45 @@ class TiXmlDeclaration : public TiXmlNode DTD tags get thrown into TiXmlUnknowns. */ -class TiXmlUnknown : public TiXmlNode -{ - public: - TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} - virtual ~TiXmlUnknown() {} - - TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); } - TiXmlUnknown& operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); return *this; } - - /// Creates a copy of this Unknown and returns it. - virtual TiXmlNode* Clone() const; - // Print this Unknown to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - - protected: - void CopyTo( TiXmlUnknown* target ) const; +class TiXmlUnknown : public TiXmlNode { +public: + TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} + virtual ~TiXmlUnknown() {} + + TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { + copy.CopyTo( this ); + } + TiXmlUnknown& operator=( const TiXmlUnknown& copy ) { + copy.CopyTo( this ); + return *this; + } + + /// Creates a copy of this Unknown and returns it. + virtual TiXmlNode* Clone() const; + // Print this Unknown to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlUnknown* ToUnknown() const { + return this; ///< Cast to a more defined type. Will return null not of the requested type. + } + virtual TiXmlUnknown* ToUnknown() { + return this; ///< Cast to a more defined type. Will return null not of the requested type. + } + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected: + void CopyTo( TiXmlUnknown* target ) const; #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); #endif - private: +private: }; @@ -1392,168 +1555,190 @@ class TiXmlUnknown : public TiXmlNode XML pieces. It can be saved, loaded, and printed to the screen. The 'value' of a document node is the xml file name. */ -class TiXmlDocument : public TiXmlNode -{ - public: - /// Create an empty document, that has no name. - TiXmlDocument(); - /// Create a document with a name. The name of the document is also the filename of the xml. - TiXmlDocument( const char * documentName ); +class TiXmlDocument : public TiXmlNode { +public: + /// Create an empty document, that has no name. + TiXmlDocument(); + /// Create a document with a name. The name of the document is also the filename of the xml. + TiXmlDocument( const char * documentName ); #ifdef TIXML_USE_STL - /// Constructor. - TiXmlDocument( const std::string& documentName ); + /// Constructor. + TiXmlDocument( const std::string& documentName ); #endif - TiXmlDocument( const TiXmlDocument& copy ); - TiXmlDocument& operator=( const TiXmlDocument& copy ); - - virtual ~TiXmlDocument() {} - - /** Load a file using the current document value. - Returns true if successful. Will delete any existing - document data before loading. - */ - bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the current document value. Returns true if successful. - bool SaveFile() const; - /// Load a file using the given filename. Returns true if successful. - bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given filename. Returns true if successful. - bool SaveFile( const char * filename ) const; - /** Load a file using the given FILE*. Returns true if successful. Note that this method - doesn't stream - the entire object pointed at by the FILE* - will be interpreted as an XML file. TinyXML doesn't stream in XML from the current - file location. Streaming may be added in the future. - */ - bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given FILE*. Returns true if successful. - bool SaveFile( FILE* ) const; + TiXmlDocument( const TiXmlDocument& copy ); + TiXmlDocument& operator=( const TiXmlDocument& copy ); + + virtual ~TiXmlDocument() {} + + /** Load a file using the current document value. + Returns true if successful. Will delete any existing + document data before loading. + */ + bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the current document value. Returns true if successful. + bool SaveFile() const; + /// Load a file using the given filename. Returns true if successful. + bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given filename. Returns true if successful. + bool SaveFile( const char * filename ) const; + /** Load a file using the given FILE*. Returns true if successful. Note that this method + doesn't stream - the entire object pointed at by the FILE* + will be interpreted as an XML file. TinyXML doesn't stream in XML from the current + file location. Streaming may be added in the future. + */ + bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given FILE*. Returns true if successful. + bool SaveFile( FILE* ) const; #ifdef TIXML_USE_STL - bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. - { - return LoadFile( filename.c_str(), encoding ); - } - bool SaveFile( const std::string& filename ) const ///< STL std::string version. - { - return SaveFile( filename.c_str() ); - } + bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) { ///< STL std::string version. + return LoadFile( filename.c_str(), encoding ); + } + bool SaveFile( const std::string& filename ) const { ///< STL std::string version. + return SaveFile( filename.c_str() ); + } #endif - /** Parse the given null terminated block of xml data. Passing in an encoding to this - method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml - to use that encoding, regardless of what TinyXml might otherwise try to detect. - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - - /** Get the root element -- the only top level element -- of the document. - In well formed XML, there should only be one. TinyXml is tolerant of - multiple elements at the document level. - */ - const TiXmlElement* RootElement() const { return FirstChildElement(); } - TiXmlElement* RootElement() { return FirstChildElement(); } - - /** If an error occurs, Error will be set to true. Also, - - The ErrorId() will contain the integer identifier of the error (not generally useful) - - The ErrorDesc() method will return the name of the error. (very useful) - - The ErrorRow() and ErrorCol() will return the location of the error (if known) - */ - bool Error() const { return error; } - - /// Contains a textual (english) description of the error if one occurs. - const char * ErrorDesc() const { return errorDesc.c_str (); } - - /** Generally, you probably want the error string ( ErrorDesc() ). But if you - prefer the ErrorId, this function will fetch it. - */ - int ErrorId() const { return errorId; } - - /** Returns the location (if known) of the error. The first column is column 1, - and the first row is row 1. A value of 0 means the row and column wasn't applicable - (memory errors, for example, have no row/column) or the parser lost the error. (An - error in the error reporting, in that case.) - - @sa SetTabSize, Row, Column - */ - int ErrorRow() const { return errorLocation.row+1; } - int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() - - /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) - to report the correct values for row and column. It does not change the output - or input in any way. - - By calling this method, with a tab size - greater than 0, the row and column of each node and attribute is stored - when the file is loaded. Very useful for tracking the DOM back in to - the source file. - - The tab size is required for calculating the location of nodes. If not - set, the default of 4 is used. The tabsize is set per document. Setting - the tabsize to 0 disables row/column tracking. - - Note that row and column tracking is not supported when using operator>>. - - The tab size needs to be enabled before the parse or load. Correct usage: - @verbatim - TiXmlDocument doc; - doc.SetTabSize( 8 ); - doc.Load( "myfile.xml" ); - @endverbatim - - @sa Row, Column - */ - void SetTabSize( int _tabsize ) { tabsize = _tabsize; } - - int TabSize() const { return tabsize; } - - /** If you have handled the error, it can be reset with this call. The error - state is automatically cleared if you Parse a new XML block. - */ - void ClearError() { error = false; - errorId = 0; - errorDesc = ""; - errorLocation.row = errorLocation.col = 0; - //errorLocation.last = 0; - } - - /** Write the document to standard out using formatted printing ("pretty print"). */ - void Print() const { Print( stdout, 0 ); } - - /* Write the document to a string using formatted printing ("pretty print"). This - will allocate a character array (new char[]) and return it as a pointer. The - calling code pust call delete[] on the return char* to avoid a memory leak. - */ - //char* PrintToMemory() const; - - /// Print this Document to a FILE stream. - virtual void Print( FILE* cfile, int depth = 0 ) const; - // [internal use] - void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - - virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; - - protected : - // [internal use] - virtual TiXmlNode* Clone() const; + /** Parse the given null terminated block of xml data. Passing in an encoding to this + method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml + to use that encoding, regardless of what TinyXml might otherwise try to detect. + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + + /** Get the root element -- the only top level element -- of the document. + In well formed XML, there should only be one. TinyXml is tolerant of + multiple elements at the document level. + */ + const TiXmlElement* RootElement() const { + return FirstChildElement(); + } + TiXmlElement* RootElement() { + return FirstChildElement(); + } + + /** If an error occurs, Error will be set to true. Also, + - The ErrorId() will contain the integer identifier of the error (not generally useful) + - The ErrorDesc() method will return the name of the error. (very useful) + - The ErrorRow() and ErrorCol() will return the location of the error (if known) + */ + bool Error() const { + return error; + } + + /// Contains a textual (english) description of the error if one occurs. + const char * ErrorDesc() const { + return errorDesc.c_str (); + } + + /** Generally, you probably want the error string ( ErrorDesc() ). But if you + prefer the ErrorId, this function will fetch it. + */ + int ErrorId() const { + return errorId; + } + + /** Returns the location (if known) of the error. The first column is column 1, + and the first row is row 1. A value of 0 means the row and column wasn't applicable + (memory errors, for example, have no row/column) or the parser lost the error. (An + error in the error reporting, in that case.) + + @sa SetTabSize, Row, Column + */ + int ErrorRow() const { + return errorLocation.row+1; + } + int ErrorCol() const { + return errorLocation.col+1; ///< The column where the error occured. See ErrorRow() + } + + /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) + to report the correct values for row and column. It does not change the output + or input in any way. + + By calling this method, with a tab size + greater than 0, the row and column of each node and attribute is stored + when the file is loaded. Very useful for tracking the DOM back in to + the source file. + + The tab size is required for calculating the location of nodes. If not + set, the default of 4 is used. The tabsize is set per document. Setting + the tabsize to 0 disables row/column tracking. + + Note that row and column tracking is not supported when using operator>>. + + The tab size needs to be enabled before the parse or load. Correct usage: + @verbatim + TiXmlDocument doc; + doc.SetTabSize( 8 ); + doc.Load( "myfile.xml" ); + @endverbatim + + @sa Row, Column + */ + void SetTabSize( int _tabsize ) { + tabsize = _tabsize; + } + + int TabSize() const { + return tabsize; + } + + /** If you have handled the error, it can be reset with this call. The error + state is automatically cleared if you Parse a new XML block. + */ + void ClearError() { + error = false; + errorId = 0; + errorDesc = ""; + errorLocation.row = errorLocation.col = 0; + //errorLocation.last = 0; + } + + /** Write the document to standard out using formatted printing ("pretty print"). */ + void Print() const { + Print( stdout, 0 ); + } + + /* Write the document to a string using formatted printing ("pretty print"). This + will allocate a character array (new char[]) and return it as a pointer. The + calling code pust call delete[] on the return char* to avoid a memory leak. + */ + //char* PrintToMemory() const; + + /// Print this Document to a FILE stream. + virtual void Print( FILE* cfile, int depth = 0 ) const; + // [internal use] + void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + + virtual const TiXmlDocument* ToDocument() const { + return this; ///< Cast to a more defined type. Will return null not of the requested type. + } + virtual TiXmlDocument* ToDocument() { + return this; ///< Cast to a more defined type. Will return null not of the requested type. + } + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected : + // [internal use] + virtual TiXmlNode* Clone() const; #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); #endif - private: - void CopyTo( TiXmlDocument* target ) const; +private: + void CopyTo( TiXmlDocument* target ) const; - bool error; - int errorId; - TIXML_STRING errorDesc; - int tabsize; - TiXmlCursor errorLocation; - bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. + bool error; + int errorId; + TIXML_STRING errorDesc; + int tabsize; + TiXmlCursor errorLocation; + bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. }; @@ -1572,7 +1757,7 @@ class TiXmlDocument : public TiXmlNode <Document> @endverbatim - Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very easy to write a *lot* of code that looks like: @verbatim @@ -1592,7 +1777,7 @@ class TiXmlDocument : public TiXmlNode @endverbatim And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity - of such code. A TiXmlHandle checks for null pointers so it is perfectly safe + of such code. A TiXmlHandle checks for null pointers so it is perfectly safe and correct to use: @verbatim @@ -1613,7 +1798,7 @@ class TiXmlDocument : public TiXmlNode What they should not be used for is iteration: @verbatim - int i=0; + int i=0; while ( true ) { TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); @@ -1624,8 +1809,8 @@ class TiXmlDocument : public TiXmlNode } @endverbatim - It seems reasonable, but it is in fact two embedded while loops. The Child method is - a linear walk to find the element, so this code would iterate much more than it needs + It seems reasonable, but it is in fact two embedded while loops. The Child method is + a linear walk to find the element, so this code would iterate much more than it needs to. Instead, prefer: @verbatim @@ -1637,83 +1822,113 @@ class TiXmlDocument : public TiXmlNode } @endverbatim */ -class TiXmlHandle -{ - public: - /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. - TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } - /// Copy constructor - TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } - TiXmlHandle operator=( const TiXmlHandle& ref ) { if ( &ref != this ) this->node = ref.node; return *this; } - - /// Return a handle to the first child node. - TiXmlHandle FirstChild() const; - /// Return a handle to the first child node with the given name. - TiXmlHandle FirstChild( const char * value ) const; - /// Return a handle to the first child element. - TiXmlHandle FirstChildElement() const; - /// Return a handle to the first child element with the given name. - TiXmlHandle FirstChildElement( const char * value ) const; - - /** Return a handle to the "index" child with the given name. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( const char* value, int index ) const; - /** Return a handle to the "index" child. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( int index ) const; - /** Return a handle to the "index" child element with the given name. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( const char* value, int index ) const; - /** Return a handle to the "index" child element. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( int index ) const; +class TiXmlHandle { +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + TiXmlHandle( TiXmlNode* _node ) { + this->node = _node; + } + /// Copy constructor + TiXmlHandle( const TiXmlHandle& ref ) { + this->node = ref.node; + } + TiXmlHandle operator=( const TiXmlHandle& ref ) { + if ( &ref != this ) this->node = ref.node; + return *this; + } + + /// Return a handle to the first child node. + TiXmlHandle FirstChild() const; + /// Return a handle to the first child node with the given name. + TiXmlHandle FirstChild( const char * value ) const; + /// Return a handle to the first child element. + TiXmlHandle FirstChildElement() const; + /// Return a handle to the first child element with the given name. + TiXmlHandle FirstChildElement( const char * value ) const; + + /** Return a handle to the "index" child with the given name. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( const char* value, int index ) const; + /** Return a handle to the "index" child. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( int index ) const; + /** Return a handle to the "index" child element with the given name. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( const char* value, int index ) const; + /** Return a handle to the "index" child element. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( int index ) const; #ifdef TIXML_USE_STL - TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } - TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } - - TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } - TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } + TiXmlHandle FirstChild( const std::string& _value ) const { + return FirstChild( _value.c_str() ); + } + TiXmlHandle FirstChildElement( const std::string& _value ) const { + return FirstChildElement( _value.c_str() ); + } + + TiXmlHandle Child( const std::string& _value, int index ) const { + return Child( _value.c_str(), index ); + } + TiXmlHandle ChildElement( const std::string& _value, int index ) const { + return ChildElement( _value.c_str(), index ); + } #endif - /** Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* ToNode() const { return node; } - /** Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } - /** Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } - /** Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } - - /** @deprecated use ToNode. - Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* Node() const { return ToNode(); } - /** @deprecated use ToElement. - Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* Element() const { return ToElement(); } - /** @deprecated use ToText() - Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* Text() const { return ToText(); } - /** @deprecated use ToUnknown() - Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* Unknown() const { return ToUnknown(); } - - private: - TiXmlNode* node; + /** Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* ToNode() const { + return node; + } + /** Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* ToElement() const { + return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); + } + /** Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* ToText() const { + return ( ( node && node->ToText() ) ? node->ToText() : 0 ); + } + /** Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* ToUnknown() const { + return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); + } + + /** @deprecated use ToNode. + Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* Node() const { + return ToNode(); + } + /** @deprecated use ToElement. + Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* Element() const { + return ToElement(); + } + /** @deprecated use ToText() + Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* Text() const { + return ToText(); + } + /** @deprecated use ToUnknown() + Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* Unknown() const { + return ToUnknown(); + } + +private: + TiXmlNode* node; }; @@ -1736,67 +1951,81 @@ class TiXmlHandle fprintf( stdout, "%s", printer.CStr() ); @endverbatim */ -class TiXmlPrinter : public TiXmlVisitor -{ - public: - TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), - buffer(), indent( " " ), lineBreak( "\n" ) {} - - virtual bool VisitEnter( const TiXmlDocument& doc ); - virtual bool VisitExit( const TiXmlDocument& doc ); - - virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); - virtual bool VisitExit( const TiXmlElement& element ); - - virtual bool Visit( const TiXmlDeclaration& declaration ); - virtual bool Visit( const TiXmlText& text ); - virtual bool Visit( const TiXmlComment& comment ); - virtual bool Visit( const TiXmlUnknown& unknown ); - - /** Set the indent characters for printing. By default 4 spaces - but tab (\t) is also useful, or null/empty string for no indentation. - */ - void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } - /// Query the indention string. - const char* Indent() { return indent.c_str(); } - /** Set the line breaking string. By default set to newline (\n). - Some operating systems prefer other characters, or can be - set to the null/empty string for no indenation. - */ - void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } - /// Query the current line breaking string. - const char* LineBreak() { return lineBreak.c_str(); } - - /** Switch over to "stream printing" which is the most dense formatting without - linebreaks. Common when the XML is needed for network transmission. - */ - void SetStreamPrinting() { indent = ""; - lineBreak = ""; - } - /// Return the result. - const char* CStr() { return buffer.c_str(); } - /// Return the length of the result string. - size_t Size() { return buffer.size(); } +class TiXmlPrinter : public TiXmlVisitor { +public: + TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), + buffer(), indent( " " ), lineBreak( "\n" ) {} + + virtual bool VisitEnter( const TiXmlDocument& doc ); + virtual bool VisitExit( const TiXmlDocument& doc ); + + virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); + virtual bool VisitExit( const TiXmlElement& element ); + + virtual bool Visit( const TiXmlDeclaration& declaration ); + virtual bool Visit( const TiXmlText& text ); + virtual bool Visit( const TiXmlComment& comment ); + virtual bool Visit( const TiXmlUnknown& unknown ); + + /** Set the indent characters for printing. By default 4 spaces + but tab (\t) is also useful, or null/empty string for no indentation. + */ + void SetIndent( const char* _indent ) { + indent = _indent ? _indent : "" ; + } + /// Query the indention string. + const char* Indent() { + return indent.c_str(); + } + /** Set the line breaking string. By default set to newline (\n). + Some operating systems prefer other characters, or can be + set to the null/empty string for no indenation. + */ + void SetLineBreak( const char* _lineBreak ) { + lineBreak = _lineBreak ? _lineBreak : ""; + } + /// Query the current line breaking string. + const char* LineBreak() { + return lineBreak.c_str(); + } + + /** Switch over to "stream printing" which is the most dense formatting without + linebreaks. Common when the XML is needed for network transmission. + */ + void SetStreamPrinting() { + indent = ""; + lineBreak = ""; + } + /// Return the result. + const char* CStr() { + return buffer.c_str(); + } + /// Return the length of the result string. + size_t Size() { + return buffer.size(); + } #ifdef TIXML_USE_STL - /// Return the result. - const std::string& Str() { return buffer; } + /// Return the result. + const std::string& Str() { + return buffer; + } #endif - private: - void DoIndent() { - for( int i=0; i<depth; ++i ) - buffer += indent; - } - void DoLineBreak() { - buffer += lineBreak; - } - - int depth; - bool simpleTextPrint; - TIXML_STRING buffer; - TIXML_STRING indent; - TIXML_STRING lineBreak; +private: + void DoIndent() { + for( int i=0; i<depth; ++i ) + buffer += indent; + } + void DoLineBreak() { + buffer += lineBreak; + } + + int depth; + bool simpleTextPrint; + TIXML_STRING buffer; + TIXML_STRING indent; + TIXML_STRING lineBreak; }; diff --git a/tinyxml/tinyxmlerror.cpp b/tinyxml/tinyxmlerror.cpp index ce96abfda5e138b1e54e7f11863cd05cfbc07e3c..7e7e1fcf29888549a8bed7f0849f622650bbb0cd 100644 --- a/tinyxml/tinyxmlerror.cpp +++ b/tinyxml/tinyxmlerror.cpp @@ -2,12 +2,12 @@ www.sourceforge.net/projects/tinyxml Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must @@ -31,22 +31,21 @@ distribution. // It also cleans up the code a bit. // -const char* TiXmlBase::errorString[ TiXmlBase::TIXML_ERROR_STRING_COUNT ] = -{ - "No error", - "Error", - "Failed to open file", - "Error parsing Element.", - "Failed to read Element name", - "Error reading Element value.", - "Error reading Attributes.", - "Error: empty tag.", - "Error reading end tag.", - "Error parsing Unknown.", - "Error parsing Comment.", - "Error parsing Declaration.", - "Error document empty.", - "Error null (0) or unexpected EOF found in input stream.", - "Error parsing CDATA.", - "Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.", +const char* TiXmlBase::errorString[ TiXmlBase::TIXML_ERROR_STRING_COUNT ] = { + "No error", + "Error", + "Failed to open file", + "Error parsing Element.", + "Failed to read Element name", + "Error reading Element value.", + "Error reading Attributes.", + "Error: empty tag.", + "Error reading end tag.", + "Error parsing Unknown.", + "Error parsing Comment.", + "Error parsing Declaration.", + "Error document empty.", + "Error null (0) or unexpected EOF found in input stream.", + "Error parsing CDATA.", + "Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.", }; diff --git a/tinyxml/tinyxmlparser.cpp b/tinyxml/tinyxmlparser.cpp index 317300f77e9c9b28ba9c715748713bce70afef09..01ff5a37c872794da0705c4c6f42e27b61720e3b 100644 --- a/tinyxml/tinyxmlparser.cpp +++ b/tinyxml/tinyxmlparser.cpp @@ -2,23 +2,23 @@ www.sourceforge.net/projects/tinyxml Original code by Lee Thomason (www.grinninglizard.com) -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any -purpose, including commercial applications, and to alter it and +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: -1. The origin of this software must not be misrepresented; you must +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source +3. This notice may not be removed or altered from any source distribution. */ @@ -40,14 +40,13 @@ distribution. // Note tha "PutString" hardcodes the same list. This // is less flexible than it appears. Changing the entries -// or order will break putstring. -TiXmlBase::Entity TiXmlBase::entity[ TiXmlBase::NUM_ENTITY ] = -{ - { "&", 5, '&' }, - { "<", 4, '<' }, - { ">", 4, '>' }, - { """, 6, '\"' }, - { "'", 6, '\'' } +// or order will break putstring. +TiXmlBase::Entity TiXmlBase::entity[ TiXmlBase::NUM_ENTITY ] = { + { "&", 5, '&' }, + { "<", 4, '<' }, + { ">", 4, '>' }, + { """, 6, '\"' }, + { "'", 6, '\'' } }; // Bunch of unicode info at: @@ -55,91 +54,91 @@ TiXmlBase::Entity TiXmlBase::entity[ TiXmlBase::NUM_ENTITY ] = // Including the basic of this table, which determines the #bytes in the // sequence from the lead byte. 1 placed for invalid sequences -- // although the result will be junk, pass it through as much as possible. -// Beware of the non-characters in UTF-8: +// Beware of the non-characters in UTF-8: // ef bb bf (Microsoft "lead bytes") // ef bf be -// ef bf bf +// ef bf bf const unsigned char TIXML_UTF_LEAD_0 = 0xefU; const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; -const int TiXmlBase::utf8ByteTable[256] = -{ - // 0 1 2 3 4 5 6 7 8 9 a b c d e f - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 - 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte - 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid +const int TiXmlBase::utf8ByteTable[256] = { + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte + 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid }; void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) { - const unsigned long BYTE_MASK = 0xBF; - const unsigned long BYTE_MARK = 0x80; - const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - - if (input < 0x80) - *length = 1; - else if ( input < 0x800 ) - *length = 2; - else if ( input < 0x10000 ) - *length = 3; - else if ( input < 0x200000 ) - *length = 4; - else - { *length = 0; return; } // This code won't covert this correctly anyway. - - output += *length; - - // Scary scary fall throughs. - switch (*length) - { - case 4: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 3: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 2: - --output; - *output = (char)((input | BYTE_MARK) & BYTE_MASK); - input >>= 6; - case 1: - --output; - *output = (char)(input | FIRST_BYTE_MARK[*length]); - } + const unsigned long BYTE_MASK = 0xBF; + const unsigned long BYTE_MARK = 0x80; + const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + + if (input < 0x80) + *length = 1; + else if ( input < 0x800 ) + *length = 2; + else if ( input < 0x10000 ) + *length = 3; + else if ( input < 0x200000 ) + *length = 4; + else { + *length = 0; // This code won't covert this correctly anyway. + return; + } + + output += *length; + + // Scary scary fall throughs. + switch (*length) { + case 4: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 3: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 2: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 1: + --output; + *output = (char)(input | FIRST_BYTE_MARK[*length]); + } } /*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) { - // This will only work for low-ascii, everything else is assumed to be a valid - // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very - // conservative approach. + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. // if ( encoding == TIXML_ENCODING_UTF8 ) // { - if ( anyByte < 127 ) - return isalpha( anyByte ); - else - return 1; // What else to do? The unicode set is huge...get the english ones right. + if ( anyByte < 127 ) + return isalpha( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. // } // else // { @@ -150,17 +149,17 @@ void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* leng /*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) { - // This will only work for low-ascii, everything else is assumed to be a valid - // letter. I'm not sure this is the best approach, but it is quite tricky trying - // to figure out alhabetical vs. not across encoding. So take a very - // conservative approach. + // This will only work for low-ascii, everything else is assumed to be a valid + // letter. I'm not sure this is the best approach, but it is quite tricky trying + // to figure out alhabetical vs. not across encoding. So take a very + // conservative approach. // if ( encoding == TIXML_ENCODING_UTF8 ) // { - if ( anyByte < 127 ) - return isalnum( anyByte ); - else - return 1; // What else to do? The unicode set is huge...get the english ones right. + if ( anyByte < 127 ) + return isalnum( anyByte ); + else + return 1; // What else to do? The unicode set is huge...get the english ones right. // } // else // { @@ -169,230 +168,211 @@ void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* leng } -class TiXmlParsingData -{ - friend class TiXmlDocument; - public: - void Stamp( const char* now, TiXmlEncoding encoding ); - - const TiXmlCursor& Cursor() const { return cursor; } - - private: - // Only used by the document! - TiXmlParsingData( const char* start, int _tabsize, int row, int col ) - { - assert( start ); - stamp = start; - tabsize = _tabsize; - cursor.row = row; - cursor.col = col; - } - - TiXmlCursor cursor; - const char* stamp; - int tabsize; +class TiXmlParsingData { + friend class TiXmlDocument; +public: + void Stamp( const char* now, TiXmlEncoding encoding ); + + const TiXmlCursor& Cursor() const { + return cursor; + } + +private: + // Only used by the document! + TiXmlParsingData( const char* start, int _tabsize, int row, int col ) { + assert( start ); + stamp = start; + tabsize = _tabsize; + cursor.row = row; + cursor.col = col; + } + + TiXmlCursor cursor; + const char* stamp; + int tabsize; }; void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) { - assert( now ); - - // Do nothing if the tabsize is 0. - if ( tabsize < 1 ) - { - return; - } - - // Get the current row, column. - int row = cursor.row; - int col = cursor.col; - const char* p = stamp; - assert( p ); - - while ( p < now ) - { - // Treat p as unsigned, so we have a happy compiler. - const unsigned char* pU = (const unsigned char*)p; - - // Code contributed by Fletcher Dunn: (modified by lee) - switch (*pU) { - case 0: - // We *should* never get here, but in case we do, don't - // advance past the terminating null character, ever - return; - - case '\r': - // bump down to the next line - ++row; - col = 0; - // Eat the character - ++p; - - // Check for \r\n sequence, and treat this as a single character - if (*p == '\n') { - ++p; - } - break; - - case '\n': - // bump down to the next line - ++row; - col = 0; - - // Eat the character - ++p; - - // Check for \n\r sequence, and treat this as a single - // character. (Yes, this bizarre thing does occur still - // on some arcane platforms...) - if (*p == '\r') { - ++p; - } - break; - - case '\t': - // Eat the character - ++p; - - // Skip to next tab stop - col = (col / tabsize + 1) * tabsize; - break; - - case TIXML_UTF_LEAD_0: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( *(p+1) && *(p+2) ) - { - // In these cases, don't advance the column. These are - // 0-width spaces. - if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) - p += 3; - else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) - p += 3; - else - { p +=3; ++col; } // A normal character. - } - } - else - { - ++p; - ++col; - } - break; - - default: - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // Eat the 1 to 4 byte utf8 character. - int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; - if ( step == 0 ) - step = 1; // Error case from bad encoding, but handle gracefully. - p += step; - - // Just advance one column, of course. - ++col; - } - else - { - ++p; - ++col; - } - break; - } - } - cursor.row = row; - cursor.col = col; - assert( cursor.row >= -1 ); - assert( cursor.col >= -1 ); - stamp = p; - assert( stamp ); + assert( now ); + + // Do nothing if the tabsize is 0. + if ( tabsize < 1 ) { + return; + } + + // Get the current row, column. + int row = cursor.row; + int col = cursor.col; + const char* p = stamp; + assert( p ); + + while ( p < now ) { + // Treat p as unsigned, so we have a happy compiler. + const unsigned char* pU = (const unsigned char*)p; + + // Code contributed by Fletcher Dunn: (modified by lee) + switch (*pU) { + case 0: + // We *should* never get here, but in case we do, don't + // advance past the terminating null character, ever + return; + + case '\r': + // bump down to the next line + ++row; + col = 0; + // Eat the character + ++p; + + // Check for \r\n sequence, and treat this as a single character + if (*p == '\n') { + ++p; + } + break; + + case '\n': + // bump down to the next line + ++row; + col = 0; + + // Eat the character + ++p; + + // Check for \n\r sequence, and treat this as a single + // character. (Yes, this bizarre thing does occur still + // on some arcane platforms...) + if (*p == '\r') { + ++p; + } + break; + + case '\t': + // Eat the character + ++p; + + // Skip to next tab stop + col = (col / tabsize + 1) * tabsize; + break; + + case TIXML_UTF_LEAD_0: + if ( encoding == TIXML_ENCODING_UTF8 ) { + if ( *(p+1) && *(p+2) ) { + // In these cases, don't advance the column. These are + // 0-width spaces. + if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) + p += 3; + else { + p +=3; // A normal character. + ++col; + } + } + } else { + ++p; + ++col; + } + break; + + default: + if ( encoding == TIXML_ENCODING_UTF8 ) { + // Eat the 1 to 4 byte utf8 character. + int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; + if ( step == 0 ) + step = 1; // Error case from bad encoding, but handle gracefully. + p += step; + + // Just advance one column, of course. + ++col; + } else { + ++p; + ++col; + } + break; + } + } + cursor.row = row; + cursor.col = col; + assert( cursor.row >= -1 ); + assert( cursor.col >= -1 ); + stamp = p; + assert( stamp ); } const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) { - if ( !p || !*p ) - { - return 0; - } - if ( encoding == TIXML_ENCODING_UTF8 ) - { - while ( *p ) - { - const unsigned char* pU = (const unsigned char*)p; - - // Skip the stupid Microsoft UTF-8 Byte order marks - if ( *(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==TIXML_UTF_LEAD_1 - && *(pU+2)==TIXML_UTF_LEAD_2 ) - { - p += 3; - continue; - } - else if(*(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==0xbfU - && *(pU+2)==0xbeU ) - { - p += 3; - continue; - } - else if(*(pU+0)==TIXML_UTF_LEAD_0 - && *(pU+1)==0xbfU - && *(pU+2)==0xbfU ) - { - p += 3; - continue; - } - - if ( IsWhiteSpace( *p ) ) // Still using old rules for white space. - ++p; - else - break; - } - } - else - { - while ( *p && IsWhiteSpace( *p ) ) - ++p; - } - - return p; + if ( !p || !*p ) { + return 0; + } + if ( encoding == TIXML_ENCODING_UTF8 ) { + while ( *p ) { + const unsigned char* pU = (const unsigned char*)p; + + // Skip the stupid Microsoft UTF-8 Byte order marks + if ( *(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==TIXML_UTF_LEAD_1 + && *(pU+2)==TIXML_UTF_LEAD_2 ) { + p += 3; + continue; + } else if(*(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==0xbfU + && *(pU+2)==0xbeU ) { + p += 3; + continue; + } else if(*(pU+0)==TIXML_UTF_LEAD_0 + && *(pU+1)==0xbfU + && *(pU+2)==0xbfU ) { + p += 3; + continue; + } + + if ( IsWhiteSpace( *p ) ) // Still using old rules for white space. + ++p; + else + break; + } + } else { + while ( *p && IsWhiteSpace( *p ) ) + ++p; + } + + return p; } #ifdef TIXML_USE_STL /*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) { - for( ;; ) - { - if ( !in->good() ) return false; + for( ;; ) { + if ( !in->good() ) return false; - int c = in->peek(); - // At this scope, we can't get to a document. So fail silently. - if ( !IsWhiteSpace( c ) || c <= 0 ) - return true; + int c = in->peek(); + // At this scope, we can't get to a document. So fail silently. + if ( !IsWhiteSpace( c ) || c <= 0 ) + return true; - *tag += (char) in->get(); - } + *tag += (char) in->get(); + } } /*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) { - //assert( character > 0 && character < 128 ); // else it won't work in utf-8 - while ( in->good() ) - { - int c = in->peek(); - if ( c == character ) - return true; - if ( c <= 0 ) // Silent failure: can't get document at this scope - return false; - - in->get(); - *tag += (char) c; - } - return false; + //assert( character > 0 && character < 128 ); // else it won't work in utf-8 + while ( in->good() ) { + int c = in->peek(); + if ( c == character ) + return true; + if ( c <= 0 ) // Silent failure: can't get document at this scope + return false; + + in->get(); + *tag += (char) c; + } + return false; } #endif @@ -401,1239 +381,1079 @@ const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) // const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) { - // Oddly, not supported on some comilers, - //name->clear(); - // So use this: - *name = ""; - assert( p ); - - // Names start with letters or underscores. - // Of course, in unicode, tinyxml has no idea what a letter *is*. The - // algorithm is generous. - // - // After that, they can be letters, underscores, numbers, - // hyphens, or colons. (Colons are valid ony for namespaces, - // but tinyxml can't tell namespaces from names.) - if ( p && *p - && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) - { - const char* start = p; - while( p && *p - && ( IsAlphaNum( (unsigned char ) *p, encoding ) - || *p == '_' - || *p == '-' - || *p == '.' - || *p == ':' ) ) - { - //(*name) += *p; // expensive - ++p; - } - if ( p-start > 0 ) { - name->assign( start, p-start ); - } - return p; - } - return 0; + // Oddly, not supported on some comilers, + //name->clear(); + // So use this: + *name = ""; + assert( p ); + + // Names start with letters or underscores. + // Of course, in unicode, tinyxml has no idea what a letter *is*. The + // algorithm is generous. + // + // After that, they can be letters, underscores, numbers, + // hyphens, or colons. (Colons are valid ony for namespaces, + // but tinyxml can't tell namespaces from names.) + if ( p && *p + && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) { + const char* start = p; + while( p && *p + && ( IsAlphaNum( (unsigned char ) *p, encoding ) + || *p == '_' + || *p == '-' + || *p == '.' + || *p == ':' ) ) { + //(*name) += *p; // expensive + ++p; + } + if ( p-start > 0 ) { + name->assign( start, p-start ); + } + return p; + } + return 0; } const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) { - // Presume an entity, and pull it out. - TIXML_STRING ent; - int i; - *length = 0; - - if ( *(p+1) && *(p+1) == '#' && *(p+2) ) - { - unsigned long ucs = 0; - ptrdiff_t delta = 0; - unsigned mult = 1; - - if ( *(p+2) == 'x' ) - { - // Hexadecimal. - if ( !*(p+3) ) return 0; - - const char* q = p+3; - q = strchr( q, ';' ); - - if ( !q || !*q ) return 0; - - delta = q-p; - --q; - - while ( *q != 'x' ) - { - if ( *q >= '0' && *q <= '9' ) - ucs += mult * (*q - '0'); - else if ( *q >= 'a' && *q <= 'f' ) - ucs += mult * (*q - 'a' + 10); - else if ( *q >= 'A' && *q <= 'F' ) - ucs += mult * (*q - 'A' + 10 ); - else - return 0; - mult *= 16; - --q; - } - } - else - { - // Decimal. - if ( !*(p+2) ) return 0; - - const char* q = p+2; - q = strchr( q, ';' ); - - if ( !q || !*q ) return 0; - - delta = q-p; - --q; - - while ( *q != '#' ) - { - if ( *q >= '0' && *q <= '9' ) - ucs += mult * (*q - '0'); - else - return 0; - mult *= 10; - --q; - } - } - if ( encoding == TIXML_ENCODING_UTF8 ) - { - // convert the UCS to UTF-8 - ConvertUTF32ToUTF8( ucs, value, length ); - } - else - { - *value = (char)ucs; - *length = 1; - } - return p + delta + 1; - } - - // Now try to match it. - for( i=0; i<NUM_ENTITY; ++i ) - { - if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 ) - { - assert( strlen( entity[i].str ) == entity[i].strLength ); - *value = entity[i].chr; - *length = 1; - return ( p + entity[i].strLength ); - } - } - - // So it wasn't an entity, its unrecognized, or something like that. - *value = *p; // Don't put back the last one, since we return it! - //*length = 1; // Leave unrecognized entities - this doesn't really work. - // Just writes strange XML. - return p+1; + // Presume an entity, and pull it out. + TIXML_STRING ent; + int i; + *length = 0; + + if ( *(p+1) && *(p+1) == '#' && *(p+2) ) { + unsigned long ucs = 0; + ptrdiff_t delta = 0; + unsigned mult = 1; + + if ( *(p+2) == 'x' ) { + // Hexadecimal. + if ( !*(p+3) ) return 0; + + const char* q = p+3; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != 'x' ) { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else if ( *q >= 'a' && *q <= 'f' ) + ucs += mult * (*q - 'a' + 10); + else if ( *q >= 'A' && *q <= 'F' ) + ucs += mult * (*q - 'A' + 10 ); + else + return 0; + mult *= 16; + --q; + } + } else { + // Decimal. + if ( !*(p+2) ) return 0; + + const char* q = p+2; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != '#' ) { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else + return 0; + mult *= 10; + --q; + } + } + if ( encoding == TIXML_ENCODING_UTF8 ) { + // convert the UCS to UTF-8 + ConvertUTF32ToUTF8( ucs, value, length ); + } else { + *value = (char)ucs; + *length = 1; + } + return p + delta + 1; + } + + // Now try to match it. + for( i=0; i<NUM_ENTITY; ++i ) { + if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 ) { + assert( strlen( entity[i].str ) == entity[i].strLength ); + *value = entity[i].chr; + *length = 1; + return ( p + entity[i].strLength ); + } + } + + // So it wasn't an entity, its unrecognized, or something like that. + *value = *p; // Don't put back the last one, since we return it! + //*length = 1; // Leave unrecognized entities - this doesn't really work. + // Just writes strange XML. + return p+1; } bool TiXmlBase::StringEqual( const char* p, - const char* tag, - bool ignoreCase, - TiXmlEncoding encoding ) + const char* tag, + bool ignoreCase, + TiXmlEncoding encoding ) { - assert( p ); - assert( tag ); - if ( !p || !*p ) - { - assert( 0 ); - return false; - } - - const char* q = p; - - if ( ignoreCase ) - { - while ( *q && *tag && ToLower( *q, encoding ) == ToLower( *tag, encoding ) ) - { - ++q; - ++tag; - } - - if ( *tag == 0 ) - return true; - } - else - { - while ( *q && *tag && *q == *tag ) - { - ++q; - ++tag; - } - - if ( *tag == 0 ) // Have we found the end of the tag, and everything equal? - return true; - } - return false; + assert( p ); + assert( tag ); + if ( !p || !*p ) { + assert( 0 ); + return false; + } + + const char* q = p; + + if ( ignoreCase ) { + while ( *q && *tag && ToLower( *q, encoding ) == ToLower( *tag, encoding ) ) { + ++q; + ++tag; + } + + if ( *tag == 0 ) + return true; + } else { + while ( *q && *tag && *q == *tag ) { + ++q; + ++tag; + } + + if ( *tag == 0 ) // Have we found the end of the tag, and everything equal? + return true; + } + return false; } -const char* TiXmlBase::ReadText( const char* p, - TIXML_STRING * text, - bool trimWhiteSpace, - const char* endTag, - bool caseInsensitive, - TiXmlEncoding encoding ) +const char* TiXmlBase::ReadText( const char* p, + TIXML_STRING * text, + bool trimWhiteSpace, + const char* endTag, + bool caseInsensitive, + TiXmlEncoding encoding ) { - *text = ""; - if ( !trimWhiteSpace // certain tags always keep whitespace - || !condenseWhiteSpace ) // if true, whitespace is always kept - { - // Keep all the white space. - while ( p && *p - && !StringEqual( p, endTag, caseInsensitive, encoding ) - ) - { - int len; - char cArr[4] = { 0, 0, 0, 0 }; - p = GetChar( p, cArr, &len, encoding ); - text->append( cArr, len ); - } - } - else - { - bool whitespace = false; - - // Remove leading white space: - p = SkipWhiteSpace( p, encoding ); - while ( p && *p - && !StringEqual( p, endTag, caseInsensitive, encoding ) ) - { - if ( *p == '\r' || *p == '\n' ) - { - whitespace = true; - ++p; - } - else if ( IsWhiteSpace( *p ) ) - { - whitespace = true; - ++p; - } - else - { - // If we've found whitespace, add it before the - // new character. Any whitespace just becomes a space. - if ( whitespace ) - { - (*text) += ' '; - whitespace = false; - } - int len; - char cArr[4] = { 0, 0, 0, 0 }; - p = GetChar( p, cArr, &len, encoding ); - if ( len == 1 ) - (*text) += cArr[0]; // more efficient - else - text->append( cArr, len ); - } - } - } - if ( p && *p ) - p += strlen( endTag ); - return ( p && *p ) ? p : 0; + *text = ""; + if ( !trimWhiteSpace // certain tags always keep whitespace + || !condenseWhiteSpace ) { // if true, whitespace is always kept + // Keep all the white space. + while ( p && *p + && !StringEqual( p, endTag, caseInsensitive, encoding ) + ) { + int len; + char cArr[4] = { 0, 0, 0, 0 }; + p = GetChar( p, cArr, &len, encoding ); + text->append( cArr, len ); + } + } else { + bool whitespace = false; + + // Remove leading white space: + p = SkipWhiteSpace( p, encoding ); + while ( p && *p + && !StringEqual( p, endTag, caseInsensitive, encoding ) ) { + if ( *p == '\r' || *p == '\n' ) { + whitespace = true; + ++p; + } else if ( IsWhiteSpace( *p ) ) { + whitespace = true; + ++p; + } else { + // If we've found whitespace, add it before the + // new character. Any whitespace just becomes a space. + if ( whitespace ) { + (*text) += ' '; + whitespace = false; + } + int len; + char cArr[4] = { 0, 0, 0, 0 }; + p = GetChar( p, cArr, &len, encoding ); + if ( len == 1 ) + (*text) += cArr[0]; // more efficient + else + text->append( cArr, len ); + } + } + } + if ( p && *p ) + p += strlen( endTag ); + return ( p && *p ) ? p : 0; } #ifdef TIXML_USE_STL void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) { - // The basic issue with a document is that we don't know what we're - // streaming. Read something presumed to be a tag (and hope), then - // identify it, and call the appropriate stream method on the tag. - // - // This "pre-streaming" will never read the closing ">" so the - // sub-tag can orient itself. - - if ( !StreamTo( in, '<', tag ) ) - { - SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - while ( in->good() ) - { - int tagIndex = (int) tag->length(); - while ( in->good() && in->peek() != '>' ) - { - int c = in->get(); - if ( c <= 0 ) - { - SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - break; - } - (*tag) += (char) c; - } - - if ( in->good() ) - { - // We now have something we presume to be a node of - // some sort. Identify it, and call the node to - // continue streaming. - TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); - - if ( node ) - { - node->StreamIn( in, tag ); - bool isElement = node->ToElement() != 0; - delete node; - node = 0; - - // If this is the root element, we're done. Parsing will be - // done by the >> operator. - if ( isElement ) - { - return; - } - } - else - { - SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - } - } - // We should have returned sooner. - SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); + // The basic issue with a document is that we don't know what we're + // streaming. Read something presumed to be a tag (and hope), then + // identify it, and call the appropriate stream method on the tag. + // + // This "pre-streaming" will never read the closing ">" so the + // sub-tag can orient itself. + + if ( !StreamTo( in, '<', tag ) ) { + SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + while ( in->good() ) { + int tagIndex = (int) tag->length(); + while ( in->good() && in->peek() != '>' ) { + int c = in->get(); + if ( c <= 0 ) { + SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + break; + } + (*tag) += (char) c; + } + + if ( in->good() ) { + // We now have something we presume to be a node of + // some sort. Identify it, and call the node to + // continue streaming. + TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); + + if ( node ) { + node->StreamIn( in, tag ); + bool isElement = node->ToElement() != 0; + delete node; + node = 0; + + // If this is the root element, we're done. Parsing will be + // done by the >> operator. + if ( isElement ) { + return; + } + } else { + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + } + } + // We should have returned sooner. + SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); } #endif const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) { - ClearError(); - - // Parse away, at the document level. Since a document - // contains nothing but other tags, most of what happens - // here is skipping white space. - if ( !p || !*p ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - // Note that, for a document, this needs to come - // before the while space skip, so that parsing - // starts from the pointer we are given. - location.Clear(); - if ( prevData ) - { - location.row = prevData->cursor.row; - location.col = prevData->cursor.col; - } - else - { - location.row = 0; - location.col = 0; - } - TiXmlParsingData data( p, TabSize(), location.row, location.col ); - location = data.Cursor(); - - if ( encoding == TIXML_ENCODING_UNKNOWN ) - { - // Check for the Microsoft UTF-8 lead bytes. - const unsigned char* pU = (const unsigned char*)p; - if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 - && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 - && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) - { - encoding = TIXML_ENCODING_UTF8; - useMicrosoftBOM = true; - } - } - - p = SkipWhiteSpace( p, encoding ); - if ( !p ) - { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); - return 0; - } - - while ( p && *p ) - { - TiXmlNode* node = Identify( p, encoding ); - if ( node ) - { - p = node->Parse( p, &data, encoding ); - LinkEndChild( node ); - } - else - { - break; - } - - // Did we get encoding info? - if ( encoding == TIXML_ENCODING_UNKNOWN - && node->ToDeclaration() ) - { - TiXmlDeclaration* dec = node->ToDeclaration(); - const char* enc = dec->Encoding(); - assert( enc ); - - if ( *enc == 0 ) - encoding = TIXML_ENCODING_UTF8; - else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) - encoding = TIXML_ENCODING_UTF8; - else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) - encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice - else - encoding = TIXML_ENCODING_LEGACY; - } - - p = SkipWhiteSpace( p, encoding ); - } - - // Was this empty? - if ( !firstChild ) { - SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); - return 0; - } - - // All is well. - return p; + ClearError(); + + // Parse away, at the document level. Since a document + // contains nothing but other tags, most of what happens + // here is skipping white space. + if ( !p || !*p ) { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + // Note that, for a document, this needs to come + // before the while space skip, so that parsing + // starts from the pointer we are given. + location.Clear(); + if ( prevData ) { + location.row = prevData->cursor.row; + location.col = prevData->cursor.col; + } else { + location.row = 0; + location.col = 0; + } + TiXmlParsingData data( p, TabSize(), location.row, location.col ); + location = data.Cursor(); + + if ( encoding == TIXML_ENCODING_UNKNOWN ) { + // Check for the Microsoft UTF-8 lead bytes. + const unsigned char* pU = (const unsigned char*)p; + if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 + && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 + && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) { + encoding = TIXML_ENCODING_UTF8; + useMicrosoftBOM = true; + } + } + + p = SkipWhiteSpace( p, encoding ); + if ( !p ) { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + while ( p && *p ) { + TiXmlNode* node = Identify( p, encoding ); + if ( node ) { + p = node->Parse( p, &data, encoding ); + LinkEndChild( node ); + } else { + break; + } + + // Did we get encoding info? + if ( encoding == TIXML_ENCODING_UNKNOWN + && node->ToDeclaration() ) { + TiXmlDeclaration* dec = node->ToDeclaration(); + const char* enc = dec->Encoding(); + assert( enc ); + + if ( *enc == 0 ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice + else + encoding = TIXML_ENCODING_LEGACY; + } + + p = SkipWhiteSpace( p, encoding ); + } + + // Was this empty? + if ( !firstChild ) { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); + return 0; + } + + // All is well. + return p; } void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) -{ - // The first error in a chain is more accurate - don't set again! - if ( error ) - return; - - assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); - error = true; - errorId = err; - errorDesc = errorString[ errorId ]; - - errorLocation.Clear(); - if ( pError && data ) - { - data->Stamp( pError, encoding ); - errorLocation = data->Cursor(); - } +{ + // The first error in a chain is more accurate - don't set again! + if ( error ) + return; + + assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); + error = true; + errorId = err; + errorDesc = errorString[ errorId ]; + + errorLocation.Clear(); + if ( pError && data ) { + data->Stamp( pError, encoding ); + errorLocation = data->Cursor(); + } } TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) { - TiXmlNode* returnNode = 0; - - p = SkipWhiteSpace( p, encoding ); - if( !p || !*p || *p != '<' ) - { - return 0; - } - - p = SkipWhiteSpace( p, encoding ); - - if ( !p || !*p ) - { - return 0; - } - - // What is this thing? - // - Elements start with a letter or underscore, but xml is reserved. - // - Comments: <!-- - // - Decleration: <?xml - // - Everthing else is unknown to tinyxml. - // - - const char* xmlHeader = { "<?xml" }; - const char* commentHeader = { "<!--" }; - const char* dtdHeader = { "<!" }; - const char* cdataHeader = { "<![CDATA[" }; - - if ( StringEqual( p, xmlHeader, true, encoding ) ) - { - #ifdef DEBUG_PARSER - TIXML_LOG( "XML parsing Declaration\n" ); - #endif - returnNode = new TiXmlDeclaration(); - } - else if ( StringEqual( p, commentHeader, false, encoding ) ) - { - #ifdef DEBUG_PARSER - TIXML_LOG( "XML parsing Comment\n" ); - #endif - returnNode = new TiXmlComment(); - } - else if ( StringEqual( p, cdataHeader, false, encoding ) ) - { - #ifdef DEBUG_PARSER - TIXML_LOG( "XML parsing CDATA\n" ); - #endif - TiXmlText* text = new TiXmlText( "" ); - text->SetCDATA( true ); - returnNode = text; - } - else if ( StringEqual( p, dtdHeader, false, encoding ) ) - { - #ifdef DEBUG_PARSER - TIXML_LOG( "XML parsing Unknown(1)\n" ); - #endif - returnNode = new TiXmlUnknown(); - } - else if ( IsAlpha( *(p+1), encoding ) - || *(p+1) == '_' ) - { - #ifdef DEBUG_PARSER - TIXML_LOG( "XML parsing Element\n" ); - #endif - returnNode = new TiXmlElement( "" ); - } - else - { - #ifdef DEBUG_PARSER - TIXML_LOG( "XML parsing Unknown(2)\n" ); - #endif - returnNode = new TiXmlUnknown(); - } - - if ( returnNode ) - { - // Set the parent, so it can report errors - returnNode->parent = this; - } - return returnNode; + TiXmlNode* returnNode = 0; + + p = SkipWhiteSpace( p, encoding ); + if( !p || !*p || *p != '<' ) { + return 0; + } + + p = SkipWhiteSpace( p, encoding ); + + if ( !p || !*p ) { + return 0; + } + + // What is this thing? + // - Elements start with a letter or underscore, but xml is reserved. + // - Comments: <!-- + // - Decleration: <?xml + // - Everthing else is unknown to tinyxml. + // + + const char* xmlHeader = { "<?xml" }; + const char* commentHeader = { "<!--" }; + const char* dtdHeader = { "<!" }; + const char* cdataHeader = { "<![CDATA[" }; + + if ( StringEqual( p, xmlHeader, true, encoding ) ) { +#ifdef DEBUG_PARSER + TIXML_LOG( "XML parsing Declaration\n" ); +#endif + returnNode = new TiXmlDeclaration(); + } else if ( StringEqual( p, commentHeader, false, encoding ) ) { +#ifdef DEBUG_PARSER + TIXML_LOG( "XML parsing Comment\n" ); +#endif + returnNode = new TiXmlComment(); + } else if ( StringEqual( p, cdataHeader, false, encoding ) ) { +#ifdef DEBUG_PARSER + TIXML_LOG( "XML parsing CDATA\n" ); +#endif + TiXmlText* text = new TiXmlText( "" ); + text->SetCDATA( true ); + returnNode = text; + } else if ( StringEqual( p, dtdHeader, false, encoding ) ) { +#ifdef DEBUG_PARSER + TIXML_LOG( "XML parsing Unknown(1)\n" ); +#endif + returnNode = new TiXmlUnknown(); + } else if ( IsAlpha( *(p+1), encoding ) + || *(p+1) == '_' ) { +#ifdef DEBUG_PARSER + TIXML_LOG( "XML parsing Element\n" ); +#endif + returnNode = new TiXmlElement( "" ); + } else { +#ifdef DEBUG_PARSER + TIXML_LOG( "XML parsing Unknown(2)\n" ); +#endif + returnNode = new TiXmlUnknown(); + } + + if ( returnNode ) { + // Set the parent, so it can report errors + returnNode->parent = this; + } + return returnNode; } #ifdef TIXML_USE_STL void TiXmlElement::StreamIn (std::istream * in, TIXML_STRING * tag) { - // We're called with some amount of pre-parsing. That is, some of "this" - // element is in "tag". Go ahead and stream to the closing ">" - while( in->good() ) - { - int c = in->get(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - (*tag) += (char) c ; - - if ( c == '>' ) - break; - } - - if ( tag->length() < 3 ) return; - - // Okay...if we are a "/>" tag, then we're done. We've read a complete tag. - // If not, identify and stream. - - if ( tag->at( tag->length() - 1 ) == '>' - && tag->at( tag->length() - 2 ) == '/' ) - { - // All good! - return; - } - else if ( tag->at( tag->length() - 1 ) == '>' ) - { - // There is more. Could be: - // text - // cdata text (which looks like another node) - // closing tag - // another node. - for ( ;; ) - { - StreamWhiteSpace( in, tag ); - - // Do we have text? - if ( in->good() && in->peek() != '<' ) - { - // Yep, text. - TiXmlText text( "" ); - text.StreamIn( in, tag ); - - // What follows text is a closing tag or another node. - // Go around again and figure it out. - continue; - } - - // We now have either a closing tag...or another node. - // We should be at a "<", regardless. - if ( !in->good() ) return; - assert( in->peek() == '<' ); - int tagIndex = (int) tag->length(); - - bool closingTag = false; - bool firstCharFound = false; - - for( ;; ) - { - if ( !in->good() ) - return; - - int c = in->peek(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - if ( c == '>' ) - break; - - *tag += (char) c; - in->get(); - - // Early out if we find the CDATA id. - if ( c == '[' && tag->size() >= 9 ) - { - size_t len = tag->size(); - const char* start = tag->c_str() + len - 9; - if ( strcmp( start, "<![CDATA[" ) == 0 ) { - assert( !closingTag ); - break; - } - } - - if ( !firstCharFound && c != '<' && !IsWhiteSpace( c ) ) - { - firstCharFound = true; - if ( c == '/' ) - closingTag = true; - } - } - // If it was a closing tag, then read in the closing '>' to clean up the input stream. - // If it was not, the streaming will be done by the tag. - if ( closingTag ) - { - if ( !in->good() ) - return; - - int c = in->get(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - assert( c == '>' ); - *tag += (char) c; - - // We are done, once we've found our closing tag. - return; - } - else - { - // If not a closing tag, id it, and stream. - const char* tagloc = tag->c_str() + tagIndex; - TiXmlNode* node = Identify( tagloc, TIXML_DEFAULT_ENCODING ); - if ( !node ) - return; - node->StreamIn( in, tag ); - delete node; - node = 0; - - // No return: go around from the beginning: text, closing tag, or node. - } - } - } + // We're called with some amount of pre-parsing. That is, some of "this" + // element is in "tag". Go ahead and stream to the closing ">" + while( in->good() ) { + int c = in->get(); + if ( c <= 0 ) { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + (*tag) += (char) c ; + + if ( c == '>' ) + break; + } + + if ( tag->length() < 3 ) return; + + // Okay...if we are a "/>" tag, then we're done. We've read a complete tag. + // If not, identify and stream. + + if ( tag->at( tag->length() - 1 ) == '>' + && tag->at( tag->length() - 2 ) == '/' ) { + // All good! + return; + } else if ( tag->at( tag->length() - 1 ) == '>' ) { + // There is more. Could be: + // text + // cdata text (which looks like another node) + // closing tag + // another node. + for ( ;; ) { + StreamWhiteSpace( in, tag ); + + // Do we have text? + if ( in->good() && in->peek() != '<' ) { + // Yep, text. + TiXmlText text( "" ); + text.StreamIn( in, tag ); + + // What follows text is a closing tag or another node. + // Go around again and figure it out. + continue; + } + + // We now have either a closing tag...or another node. + // We should be at a "<", regardless. + if ( !in->good() ) return; + assert( in->peek() == '<' ); + int tagIndex = (int) tag->length(); + + bool closingTag = false; + bool firstCharFound = false; + + for( ;; ) { + if ( !in->good() ) + return; + + int c = in->peek(); + if ( c <= 0 ) { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + if ( c == '>' ) + break; + + *tag += (char) c; + in->get(); + + // Early out if we find the CDATA id. + if ( c == '[' && tag->size() >= 9 ) { + size_t len = tag->size(); + const char* start = tag->c_str() + len - 9; + if ( strcmp( start, "<![CDATA[" ) == 0 ) { + assert( !closingTag ); + break; + } + } + + if ( !firstCharFound && c != '<' && !IsWhiteSpace( c ) ) { + firstCharFound = true; + if ( c == '/' ) + closingTag = true; + } + } + // If it was a closing tag, then read in the closing '>' to clean up the input stream. + // If it was not, the streaming will be done by the tag. + if ( closingTag ) { + if ( !in->good() ) + return; + + int c = in->get(); + if ( c <= 0 ) { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + assert( c == '>' ); + *tag += (char) c; + + // We are done, once we've found our closing tag. + return; + } else { + // If not a closing tag, id it, and stream. + const char* tagloc = tag->c_str() + tagIndex; + TiXmlNode* node = Identify( tagloc, TIXML_DEFAULT_ENCODING ); + if ( !node ) + return; + node->StreamIn( in, tag ); + delete node; + node = 0; + + // No return: go around from the beginning: text, closing tag, or node. + } + } + } } #endif const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) { - p = SkipWhiteSpace( p, encoding ); - TiXmlDocument* document = GetDocument(); - - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding ); - return 0; - } - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - - if ( *p != '<' ) - { - if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding ); - return 0; - } - - p = SkipWhiteSpace( p+1, encoding ); - - // Read the name. - const char* pErr = p; - - p = ReadName( p, &value, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding ); - return 0; - } - - TIXML_STRING endTag ("</"); - endTag += value; - - // Check for and read attributes. Also look for an empty - // tag or an end tag. - while ( p && *p ) - { - pErr = p; - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); - return 0; - } - if ( *p == '/' ) - { - ++p; - // Empty tag. - if ( *p != '>' ) - { - if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding ); - return 0; - } - return (p+1); - } - else if ( *p == '>' ) - { - // Done with attributes (if there were any.) - // Read the value -- which can include other - // elements -- read the end tag, and return. - ++p; - p = ReadValue( p, data, encoding ); // Note this is an Element method, and will set the error if one happens. - if ( !p || !*p ) { - // We were looking for the end tag, but found nothing. - // Fix for [ 1663758 ] Failure to report error on bad XML - if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); - return 0; - } - - // We should find the end tag now - // note that: - // </foo > and - // </foo> - // are both valid end tags. - if ( StringEqual( p, endTag.c_str(), false, encoding ) ) - { - p += endTag.length(); - p = SkipWhiteSpace( p, encoding ); - if ( p && *p && *p == '>' ) { - ++p; - return p; - } - if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); - return 0; - } - else - { - if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); - return 0; - } - } - else - { - // Try to read an attribute: - TiXmlAttribute* attrib = new TiXmlAttribute(); - if ( !attrib ) - { - return 0; - } - - attrib->SetDocument( document ); - pErr = p; - p = attrib->Parse( p, data, encoding ); - - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding ); - delete attrib; - return 0; - } - - // Handle the strange case of double attributes: - #ifdef TIXML_USE_STL - TiXmlAttribute* node = attributeSet.Find( attrib->NameTStr() ); - #else - TiXmlAttribute* node = attributeSet.Find( attrib->Name() ); - #endif - if ( node ) - { - if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding ); - delete attrib; - return 0; - } - - attributeSet.Add( attrib ); - } - } - return p; + p = SkipWhiteSpace( p, encoding ); + TiXmlDocument* document = GetDocument(); + + if ( !p || !*p ) { + if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding ); + return 0; + } + + if ( data ) { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + + if ( *p != '<' ) { + if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding ); + return 0; + } + + p = SkipWhiteSpace( p+1, encoding ); + + // Read the name. + const char* pErr = p; + + p = ReadName( p, &value, encoding ); + if ( !p || !*p ) { + if ( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding ); + return 0; + } + + TIXML_STRING endTag ("</"); + endTag += value; + + // Check for and read attributes. Also look for an empty + // tag or an end tag. + while ( p && *p ) { + pErr = p; + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); + return 0; + } + if ( *p == '/' ) { + ++p; + // Empty tag. + if ( *p != '>' ) { + if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding ); + return 0; + } + return (p+1); + } else if ( *p == '>' ) { + // Done with attributes (if there were any.) + // Read the value -- which can include other + // elements -- read the end tag, and return. + ++p; + p = ReadValue( p, data, encoding ); // Note this is an Element method, and will set the error if one happens. + if ( !p || !*p ) { + // We were looking for the end tag, but found nothing. + // Fix for [ 1663758 ] Failure to report error on bad XML + if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); + return 0; + } + + // We should find the end tag now + // note that: + // </foo > and + // </foo> + // are both valid end tags. + if ( StringEqual( p, endTag.c_str(), false, encoding ) ) { + p += endTag.length(); + p = SkipWhiteSpace( p, encoding ); + if ( p && *p && *p == '>' ) { + ++p; + return p; + } + if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); + return 0; + } else { + if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); + return 0; + } + } else { + // Try to read an attribute: + TiXmlAttribute* attrib = new TiXmlAttribute(); + if ( !attrib ) { + return 0; + } + + attrib->SetDocument( document ); + pErr = p; + p = attrib->Parse( p, data, encoding ); + + if ( !p || !*p ) { + if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding ); + delete attrib; + return 0; + } + + // Handle the strange case of double attributes: +#ifdef TIXML_USE_STL + TiXmlAttribute* node = attributeSet.Find( attrib->NameTStr() ); +#else + TiXmlAttribute* node = attributeSet.Find( attrib->Name() ); +#endif + if ( node ) { + if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding ); + delete attrib; + return 0; + } + + attributeSet.Add( attrib ); + } + } + return p; } const char* TiXmlElement::ReadValue( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) { - TiXmlDocument* document = GetDocument(); - - // Read in text and elements in any order. - const char* pWithWhiteSpace = p; - p = SkipWhiteSpace( p, encoding ); - - while ( p && *p ) - { - if ( *p != '<' ) - { - // Take what we have, make a text element. - TiXmlText* textNode = new TiXmlText( "" ); - - if ( !textNode ) - { - return 0; - } - - if ( TiXmlBase::IsWhiteSpaceCondensed() ) - { - p = textNode->Parse( p, data, encoding ); - } - else - { - // Special case: we want to keep the white space - // so that leading spaces aren't removed. - p = textNode->Parse( pWithWhiteSpace, data, encoding ); - } - - if ( !textNode->Blank() ) - LinkEndChild( textNode ); - else - delete textNode; - } - else - { - // We hit a '<' - // Have we hit a new element or an end tag? This could also be - // a TiXmlText in the "CDATA" style. - if ( StringEqual( p, "</", false, encoding ) ) - { - return p; - } - else - { - TiXmlNode* node = Identify( p, encoding ); - if ( node ) - { - p = node->Parse( p, data, encoding ); - LinkEndChild( node ); - } - else - { - return 0; - } - } - } - pWithWhiteSpace = p; - p = SkipWhiteSpace( p, encoding ); - } - - if ( !p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE, 0, 0, encoding ); - } - return p; + TiXmlDocument* document = GetDocument(); + + // Read in text and elements in any order. + const char* pWithWhiteSpace = p; + p = SkipWhiteSpace( p, encoding ); + + while ( p && *p ) { + if ( *p != '<' ) { + // Take what we have, make a text element. + TiXmlText* textNode = new TiXmlText( "" ); + + if ( !textNode ) { + return 0; + } + + if ( TiXmlBase::IsWhiteSpaceCondensed() ) { + p = textNode->Parse( p, data, encoding ); + } else { + // Special case: we want to keep the white space + // so that leading spaces aren't removed. + p = textNode->Parse( pWithWhiteSpace, data, encoding ); + } + + if ( !textNode->Blank() ) + LinkEndChild( textNode ); + else + delete textNode; + } else { + // We hit a '<' + // Have we hit a new element or an end tag? This could also be + // a TiXmlText in the "CDATA" style. + if ( StringEqual( p, "</", false, encoding ) ) { + return p; + } else { + TiXmlNode* node = Identify( p, encoding ); + if ( node ) { + p = node->Parse( p, data, encoding ); + LinkEndChild( node ); + } else { + return 0; + } + } + } + pWithWhiteSpace = p; + p = SkipWhiteSpace( p, encoding ); + } + + if ( !p ) { + if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE, 0, 0, encoding ); + } + return p; } #ifdef TIXML_USE_STL void TiXmlUnknown::StreamIn( std::istream * in, TIXML_STRING * tag ) { - while ( in->good() ) - { - int c = in->get(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - (*tag) += (char) c; - - if ( c == '>' ) - { - // All is well. - return; - } - } + while ( in->good() ) { + int c = in->get(); + if ( c <= 0 ) { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + (*tag) += (char) c; + + if ( c == '>' ) { + // All is well. + return; + } + } } #endif const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) { - TiXmlDocument* document = GetDocument(); - p = SkipWhiteSpace( p, encoding ); - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - if ( !p || !*p || *p != '<' ) - { - if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding ); - return 0; - } - ++p; - value = ""; - - while ( p && *p && *p != '>' ) - { - value += *p; - ++p; - } - - if ( !p ) - { - if ( document ) - document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding ); - } - if ( p && *p == '>' ) - return p+1; - return p; + TiXmlDocument* document = GetDocument(); + p = SkipWhiteSpace( p, encoding ); + + if ( data ) { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + if ( !p || !*p || *p != '<' ) { + if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding ); + return 0; + } + ++p; + value = ""; + + while ( p && *p && *p != '>' ) { + value += *p; + ++p; + } + + if ( !p ) { + if ( document ) + document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding ); + } + if ( p && *p == '>' ) + return p+1; + return p; } #ifdef TIXML_USE_STL void TiXmlComment::StreamIn( std::istream * in, TIXML_STRING * tag ) { - while ( in->good() ) - { - int c = in->get(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - (*tag) += (char) c; - - if ( c == '>' - && tag->at( tag->length() - 2 ) == '-' - && tag->at( tag->length() - 3 ) == '-' ) - { - // All is well. - return; - } - } + while ( in->good() ) { + int c = in->get(); + if ( c <= 0 ) { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + (*tag) += (char) c; + + if ( c == '>' + && tag->at( tag->length() - 2 ) == '-' + && tag->at( tag->length() - 3 ) == '-' ) { + // All is well. + return; + } + } } #endif const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) { - TiXmlDocument* document = GetDocument(); - value = ""; - - p = SkipWhiteSpace( p, encoding ); - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - const char* startTag = "<!--"; - const char* endTag = "-->"; - - if ( !StringEqual( p, startTag, false, encoding ) ) - { - if ( document ) - document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); - return 0; - } - p += strlen( startTag ); - - // [ 1475201 ] TinyXML parses entities in comments - // Oops - ReadText doesn't work, because we don't want to parse the entities. - // p = ReadText( p, &value, false, endTag, false, encoding ); - // - // from the XML spec: - /* - [Definition: Comments may appear anywhere in a document outside other markup; in addition, - they may appear within the document type declaration at places allowed by the grammar. - They are not part of the document's character data; an XML processor MAY, but need not, - make it possible for an application to retrieve the text of comments. For compatibility, - the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity - references MUST NOT be recognized within comments. - - An example of a comment: - - <!-- declarations for <head> & <body> --> - */ - - value = ""; - // Keep all the white space. - while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) - { - value.append( p, 1 ); - ++p; - } - if ( p && *p ) - p += strlen( endTag ); - - return p; + TiXmlDocument* document = GetDocument(); + value = ""; + + p = SkipWhiteSpace( p, encoding ); + + if ( data ) { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + const char* startTag = "<!--"; + const char* endTag = "-->"; + + if ( !StringEqual( p, startTag, false, encoding ) ) { + if ( document ) + document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + + // [ 1475201 ] TinyXML parses entities in comments + // Oops - ReadText doesn't work, because we don't want to parse the entities. + // p = ReadText( p, &value, false, endTag, false, encoding ); + // + // from the XML spec: + /* + [Definition: Comments may appear anywhere in a document outside other markup; in addition, + they may appear within the document type declaration at places allowed by the grammar. + They are not part of the document's character data; an XML processor MAY, but need not, + make it possible for an application to retrieve the text of comments. For compatibility, + the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity + references MUST NOT be recognized within comments. + + An example of a comment: + + <!-- declarations for <head> & <body> --> + */ + + value = ""; + // Keep all the white space. + while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) { + value.append( p, 1 ); + ++p; + } + if ( p && *p ) + p += strlen( endTag ); + + return p; } const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) { - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) return 0; - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - // Read the name, the '=' and the value. - const char* pErr = p; - p = ReadName( p, &name, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); - return 0; - } - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p || *p != '=' ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - - ++p; // skip '=' - p = SkipWhiteSpace( p, encoding ); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - - const char* end; - const char SINGLE_QUOTE = '\''; - const char DOUBLE_QUOTE = '\"'; - - if ( *p == SINGLE_QUOTE ) - { - ++p; - end = "\'"; // single quote in string - p = ReadText( p, &value, false, end, false, encoding ); - } - else if ( *p == DOUBLE_QUOTE ) - { - ++p; - end = "\""; // double quote in string - p = ReadText( p, &value, false, end, false, encoding ); - } - else - { - // All attribute values should be in single or double quotes. - // But this is such a common error that the parser will try - // its best, even without them. - value = ""; - while ( p && *p // existence - && !IsWhiteSpace( *p ) // whitespace - && *p != '/' && *p != '>' ) // tag end - { - if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { - // [ 1451649 ] Attribute values with trailing quotes not handled correctly - // We did not have an opening quote but seem to have a - // closing one. Give up and throw an error. - if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); - return 0; - } - value += *p; - ++p; - } - } - return p; + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) return 0; + + if ( data ) { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + // Read the name, the '=' and the value. + const char* pErr = p; + p = ReadName( p, &name, encoding ); + if ( !p || !*p ) { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); + return 0; + } + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p || *p != '=' ) { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + ++p; // skip '=' + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + + const char* end; + const char SINGLE_QUOTE = '\''; + const char DOUBLE_QUOTE = '\"'; + + if ( *p == SINGLE_QUOTE ) { + ++p; + end = "\'"; // single quote in string + p = ReadText( p, &value, false, end, false, encoding ); + } else if ( *p == DOUBLE_QUOTE ) { + ++p; + end = "\""; // double quote in string + p = ReadText( p, &value, false, end, false, encoding ); + } else { + // All attribute values should be in single or double quotes. + // But this is such a common error that the parser will try + // its best, even without them. + value = ""; + while ( p && *p // existence + && !IsWhiteSpace( *p ) // whitespace + && *p != '/' && *p != '>' ) { // tag end + if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { + // [ 1451649 ] Attribute values with trailing quotes not handled correctly + // We did not have an opening quote but seem to have a + // closing one. Give up and throw an error. + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); + return 0; + } + value += *p; + ++p; + } + } + return p; } #ifdef TIXML_USE_STL void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) { - while ( in->good() ) - { - int c = in->peek(); - if ( !cdata && (c == '<' ) ) - { - return; - } - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - - (*tag) += (char) c; - in->get(); // "commits" the peek made above - - if ( cdata && c == '>' && tag->size() >= 3 ) { - size_t len = tag->size(); - if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { - // terminator of cdata. - return; - } - } - } + while ( in->good() ) { + int c = in->peek(); + if ( !cdata && (c == '<' ) ) { + return; + } + if ( c <= 0 ) { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + + (*tag) += (char) c; + in->get(); // "commits" the peek made above + + if ( cdata && c == '>' && tag->size() >= 3 ) { + size_t len = tag->size(); + if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { + // terminator of cdata. + return; + } + } + } } #endif const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) { - value = ""; - TiXmlDocument* document = GetDocument(); - - if ( data ) - { - data->Stamp( p, encoding ); - location = data->Cursor(); - } - - const char* const startTag = "<![CDATA["; - const char* const endTag = "]]>"; - - if ( cdata || StringEqual( p, startTag, false, encoding ) ) - { - cdata = true; - - if ( !StringEqual( p, startTag, false, encoding ) ) - { - if ( document ) - document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); - return 0; - } - p += strlen( startTag ); - - // Keep all the white space, ignore the encoding, etc. - while ( p && *p - && !StringEqual( p, endTag, false, encoding ) - ) - { - value += *p; - ++p; - } - - TIXML_STRING dummy; - p = ReadText( p, &dummy, false, endTag, false, encoding ); - return p; - } - else - { - bool ignoreWhite = true; - - const char* end = "<"; - p = ReadText( p, &value, ignoreWhite, end, false, encoding ); - if ( p && *p ) - return p-1; // don't truncate the '<' - return 0; - } + value = ""; + TiXmlDocument* document = GetDocument(); + + if ( data ) { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + + const char* const startTag = "<![CDATA["; + const char* const endTag = "]]>"; + + if ( cdata || StringEqual( p, startTag, false, encoding ) ) { + cdata = true; + + if ( !StringEqual( p, startTag, false, encoding ) ) { + if ( document ) + document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + + // Keep all the white space, ignore the encoding, etc. + while ( p && *p + && !StringEqual( p, endTag, false, encoding ) + ) { + value += *p; + ++p; + } + + TIXML_STRING dummy; + p = ReadText( p, &dummy, false, endTag, false, encoding ); + return p; + } else { + bool ignoreWhite = true; + + const char* end = "<"; + p = ReadText( p, &value, ignoreWhite, end, false, encoding ); + if ( p && *p ) + return p-1; // don't truncate the '<' + return 0; + } } #ifdef TIXML_USE_STL void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) { - while ( in->good() ) - { - int c = in->get(); - if ( c <= 0 ) - { - TiXmlDocument* document = GetDocument(); - if ( document ) - document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); - return; - } - (*tag) += (char) c; - - if ( c == '>' ) - { - // All is well. - return; - } - } + while ( in->good() ) { + int c = in->get(); + if ( c <= 0 ) { + TiXmlDocument* document = GetDocument(); + if ( document ) + document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); + return; + } + (*tag) += (char) c; + + if ( c == '>' ) { + // All is well. + return; + } + } } #endif const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) { - p = SkipWhiteSpace( p, _encoding ); - // Find the beginning, find the end, and look for - // the stuff in-between. - TiXmlDocument* document = GetDocument(); - if ( !p || !*p || !StringEqual( p, "<?xml", true, _encoding ) ) - { - if ( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); - return 0; - } - if ( data ) - { - data->Stamp( p, _encoding ); - location = data->Cursor(); - } - p += 5; - - version = ""; - encoding = ""; - standalone = ""; - - while ( p && *p ) - { - if ( *p == '>' ) - { - ++p; - return p; - } - - p = SkipWhiteSpace( p, _encoding ); - if ( StringEqual( p, "version", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - version = attrib.Value(); - } - else if ( StringEqual( p, "encoding", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - encoding = attrib.Value(); - } - else if ( StringEqual( p, "standalone", true, _encoding ) ) - { - TiXmlAttribute attrib; - p = attrib.Parse( p, data, _encoding ); - standalone = attrib.Value(); - } - else - { - // Read over whatever it is. - while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) - ++p; - } - } - return 0; + p = SkipWhiteSpace( p, _encoding ); + // Find the beginning, find the end, and look for + // the stuff in-between. + TiXmlDocument* document = GetDocument(); + if ( !p || !*p || !StringEqual( p, "<?xml", true, _encoding ) ) { + if ( document ) document->SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); + return 0; + } + if ( data ) { + data->Stamp( p, _encoding ); + location = data->Cursor(); + } + p += 5; + + version = ""; + encoding = ""; + standalone = ""; + + while ( p && *p ) { + if ( *p == '>' ) { + ++p; + return p; + } + + p = SkipWhiteSpace( p, _encoding ); + if ( StringEqual( p, "version", true, _encoding ) ) { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + version = attrib.Value(); + } else if ( StringEqual( p, "encoding", true, _encoding ) ) { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + encoding = attrib.Value(); + } else if ( StringEqual( p, "standalone", true, _encoding ) ) { + TiXmlAttribute attrib; + p = attrib.Parse( p, data, _encoding ); + standalone = attrib.Value(); + } else { + // Read over whatever it is. + while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) + ++p; + } + } + return 0; } bool TiXmlText::Blank() const { - for ( unsigned i=0; i<value.length(); i++ ) - if ( !IsWhiteSpace( value[i] ) ) - return false; - return true; + for ( unsigned i=0; i<value.length(); i++ ) + if ( !IsWhiteSpace( value[i] ) ) + return false; + return true; }