diff --git a/CMakeLists.txt b/CMakeLists.txt index 524b8ce0cd523d71f43ec1d904b6668667e38e8a..4fdc6e3769c0296156dbd2e59676556a9b9e2bd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ # -DCMAKE_CXX_COMPILER:STRING=clang++ -DCMAKE_C_COMPILER:STRING=clang . # -DCMAKE_BUILD_TYPE:STRING=Debug (default Release) # -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON (default OFF) +# -DBUILD_TESTING=ON (default OFF) #-------------------------------------------------------------------------- cmake_minimum_required(VERSION 2.8 FATAL_ERROR) @@ -16,12 +17,11 @@ set(JPSCORE_VERSION ${JPSCORE_MAJOR_VERSION}.${JPSCORE_MINOR_VERSION}.${JPSCORE_PATCH_VERSION}) message( STATUS "JPSCORE_VERSION: " ${JPSCORE_VERSION} ) -# # configure_file ( -# # "${CMAKE_SOURCE_DIR}/Config.h.in" -# # "${CMAKE_BINARY_DIR}/Config.h" -# # ) -# #include_directories ("${CMAKE_BINARY_DIR}") +if(NOT BUILD_TESTING) + set(BUILD_TESTING OFF) +endif(NOT BUILD_TESTING) +message( STATUS "BUILD_TESTING: " ${BUILD_TESTING} ) if(NOT DEFINED PROCESSOR_COUNT) # Unknown: set(PROCESSOR_COUNT 0) @@ -33,15 +33,6 @@ if(NOT DEFINED PROCESSOR_COUNT) list(LENGTH procs PROCESSOR_COUNT) endif(EXISTS "${cpuinfo_file}") - # Mac: - # if(APPLE) - # find_program(cmd_sys_pro "system_profiler") - # if(cmd_sys_pro) - # execute_process(COMMAND ${cmd_sys_pro} OUTPUT_VARIABLE info) - # string(REGEX REPLACE "^.*Total Number Of Cores: ([0-9]+).*$" "\\1" - # PROCESSOR_COUNT "${info}") - # endif(cmd_sys_pro) - # endif(APPLE) # Windows: if(WIN32) @@ -50,8 +41,6 @@ if(NOT DEFINED PROCESSOR_COUNT) endif(NOT DEFINED PROCESSOR_COUNT) if(PROCESSOR_COUNT) - # add 1 should be magic! http://www.kitware.com/blog/home/post/63 - #math(EXPR PROCESSOR_COUNT "${PROCESSOR_COUNT} + 1") message( STATUS "PROCESSOR_COUNT: " ${PROCESSOR_COUNT}) set(CTEST_BUILD_FLAGS "-j${PROCESSOR_COUNT}") endif(PROCESSOR_COUNT) @@ -104,8 +93,7 @@ FIND_PACKAGE(CGAL QUIET) if(CGAL_FOUND) include (${CGAL_USE_FILE}) INCLUDE_DIRECTORIES(${CGAL_CORE_INCLUDE_DIR}) - add_definitions(-D_CGAL=1) - target_link_libraries (jpscore ${CGAL_CORE_LIBRARY}) + add_definitions(-D_CGAL=1) message (SEND_ERROR "${CGAL_FOUND}") message (FATAL_ERROR "${CGAL_CORE_INCLUDE_DIR}") message (SEND_ERROR " Erreur: ${CGAL_FOUND}") @@ -115,7 +103,10 @@ else(CGAL_FOUND) endif(CGAL_FOUND) # test files: all cpp-files in Utest -file(GLOB test_files "${CMAKE_TEST_DIR}/*.cpp") +if(BUILD_TESTING) + file(GLOB test_files "${CMAKE_TEST_DIR}/*.cpp") +endif(BUILD_TESTING) + set ( source_files main.cpp Simulation.cpp @@ -269,7 +260,7 @@ set ( header_files add_library ( core SHARED ${source_files} ) -#add_library(core OBJECT ${source_files} ${header_files}) + #Target add_executable( jpscore main.cpp @@ -303,33 +294,33 @@ else(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_BUILD_TYPE MATCHES Debug) endif(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_BUILD_TYPE MATCHES Debug) # ----------------------------- cTest ------------------------------------------ -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 -add_test (jpscore_compile ${CMAKE_CTEST_COMMAND} - --build-and-test "${CMAKE_SOURCE_DIR}" "${EXECUTABLE_OUTPUT_PATH}" #"${CMAKE_BINARY_DIR}" - --build-generator ${CMAKE_GENERATOR} - --build-makeprogram ${CMAKE_MAKE_PROGRAM} -j${PROCESSOR_COUNT} - --build-two-config - --build-exe-dir ${EXECUTABLE_OUTPUT_PATH} # todo wo soll der exe hin?: ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - --build-project JPScore - --test-command jpscore --ini=${CMAKE_SOURCE_DIR}/inputfiles/Default/ini.xml - ) +if(BUILD_TESTING) + 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 + add_test (jpscore_compile ${CMAKE_CTEST_COMMAND} + --build-and-test "${CMAKE_SOURCE_DIR}" "${EXECUTABLE_OUTPUT_PATH}" #"${CMAKE_BINARY_DIR}" + --build-generator ${CMAKE_GENERATOR} + --build-makeprogram ${CMAKE_MAKE_PROGRAM} -j${PROCESSOR_COUNT} + --build-two-config + --build-exe-dir ${EXECUTABLE_OUTPUT_PATH} # todo wo soll der exe hin?: ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + --build-project JPScore + --test-command jpscore --ini=${CMAKE_SOURCE_DIR}/inputfiles/Default/ini.xml + ) -foreach (test_src ${test_files}) - GET_FILENAME_COMPONENT(test ${test_src} NAME_WE) - add_executable( ${test} ${test_src}) - target_link_libraries (${test} core) - add_test(NAME ${test} COMMAND ${test}) -endforeach(test_src ${test_files}) - - -find_package(PythonInterp) -if(PYTHONINTERP_FOUND) - message(STATUS "Found Python: " ${PYTHON_EXECUTABLE}) - message(STATUS "run: " ${CMAKE_SOURCE_DIR}/Utest/testflow.py) - set (test_parameters "${CMAKE_SOURCE_DIR}") - add_test(NAME flow COMMAND "${CMAKE_TEST_DIR}/testflow.py" "${test_parameters}") - #add_test(testtime "${CMAKE_SOURCE_DIR}/Utest/run.py") -endif(PYTHONINTERP_FOUND) + foreach (test_src ${test_files}) + GET_FILENAME_COMPONENT(test ${test_src} NAME_WE) + add_executable( ${test} ${test_src}) + target_link_libraries (${test} core) + add_test(NAME ${test} COMMAND ${test}) + endforeach(test_src ${test_files}) + + find_package(PythonInterp) + if(PYTHONINTERP_FOUND) + message(STATUS "Found Python: " ${PYTHON_EXECUTABLE}) + message(STATUS "run: " ${CMAKE_SOURCE_DIR}/Utest/testflow.py) + set (test_parameters "${CMAKE_SOURCE_DIR}") + add_test(NAME flow COMMAND "${CMAKE_TEST_DIR}/testflow.py" "${test_parameters}") + endif(PYTHONINTERP_FOUND) +endif(BUILD_TESTING) diff --git a/IO/IODispatcher.cpp b/IO/IODispatcher.cpp index 4fb86963fde44cfa9f9138c8af479e7fd3560554..bda6af9deaddf9225808d1051ba5a22324019639 100644 --- a/IO/IODispatcher.cpp +++ b/IO/IODispatcher.cpp @@ -37,263 +37,263 @@ using namespace std; IODispatcher::IODispatcher() { - pHandlers = vector<OutputHandler*>(); + pHandlers = vector<OutputHandler*>(); } IODispatcher::~IODispatcher() { - for (int i = 0; i < (int) pHandlers.size(); i++) - delete pHandlers[i]; - pHandlers.clear(); + for (int i = 0; i < (int) pHandlers.size(); i++) + delete pHandlers[i]; + pHandlers.clear(); } void IODispatcher::AddIO(OutputHandler* ioh) { - pHandlers.push_back(ioh); + pHandlers.push_back(ioh); } const vector<OutputHandler*>& IODispatcher::GetIOHandlers() { - return pHandlers; + return pHandlers; } void IODispatcher::Write(const std::string& str) { - for (vector<OutputHandler*>::iterator it = pHandlers.begin(); - it != pHandlers.end(); ++it) { - (*it)->Write(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; + 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()); - } - } - } - - // 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); + // 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()); + } + } + + } + } + } + } + } + } + } + + //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); + 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"); + Write("</trajectories>\n"); } @@ -302,7 +302,7 @@ void IODispatcher::WriteFooter() { */ TrajectoriesFLAT::TrajectoriesFLAT() : - IODispatcher() { + IODispatcher() { } void TrajectoriesFLAT::WriteHeader(int nPeds, double fps, Building* building, int seed) { @@ -314,22 +314,22 @@ 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); - } - } - } + 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() { @@ -346,56 +346,56 @@ 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(""); + 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; + 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) { @@ -410,121 +410,121 @@ 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"); -// tmp.append("<frameCount>xxxxxxx</frameCount>\n"); - tmp.append("\t</header>\n"); - Write(tmp); + 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); } 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"); + // 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); + 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"); + 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; + //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 0e0e50227224955e5bac72232d582fb5532b6fba..6fcfb4169638374581fe6d05a0ee37a274cd06a1 100644 --- a/IO/IODispatcher.h +++ b/IO/IODispatcher.h @@ -27,7 +27,7 @@ */ #ifndef _IODISPATCHER_H -#define _IODISPATCHER_H +#define _IODISPATCHER_H #include "OutputHandler.h" #include "../geometry/Building.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,54 +74,54 @@ public: 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 */ +#endif /* _IODISPATCHER_H */ diff --git a/IO/OutputHandler.cpp b/IO/OutputHandler.cpp index e31aae7e00fef36da3e9987d1d5e4b618a3612a9..b6fc674a22862aefc0cb9cfee53df48f8dda01fe 100644 --- a/IO/OutputHandler.cpp +++ b/IO/OutputHandler.cpp @@ -35,35 +35,35 @@ using namespace std; void OutputHandler::Write(string str) { - if (this != NULL) - cout << str << endl; + 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"; + 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; + if (this != NULL) + cout << str << endl; } FileHandler::FileHandler(const char *fn) { @@ -88,13 +88,13 @@ void FileHandler::Write(string str) { } 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(); + 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) { @@ -105,7 +105,7 @@ TraVisToHandler::TraVisToHandler(string host, int port) { } TraVisToHandler::~TraVisToHandler(){ - delete client; + delete client; } void TraVisToHandler::Write(string str) { diff --git a/IO/OutputHandler.h b/IO/OutputHandler.h index 855d85ad4b6f72f53d0b82e510767cf822fff2b6..e63beaccfbd25bb9a61f668ead0e33c91d9d9298 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 d095a4bbfb0281858ed271f4fe717725547b819c..2ece7bf8468b06f34e0086d84490112408481bb7 100644 --- a/IO/TraVisToClient.cpp +++ b/IO/TraVisToClient.cpp @@ -418,8 +418,8 @@ TraVisToClient::shutdownAndCloseSocket(socket_t sock) { //FIXME: //if (SOCKET_ERROR == closesocket(tcpSocket)) { - // derror("closesocket() failed"); - // status = false; + // derror("closesocket() failed"); + // status = false; //} dtrace("leaving shutdownAndCloseSocket()"); diff --git a/IO/TraVisToClient.h b/IO/TraVisToClient.h index 9b37e54ebfc18bad87eff0ea5c2261350bec36eb..b4033a2b8429edbbacd0247e034ce22584c69196 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 +#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 05925339a4071be3a877a363dfb2a053fec13f90..90e1395232513697a465a741090c5ea345cd8561 100644 --- a/Simulation.cpp +++ b/Simulation.cpp @@ -33,28 +33,28 @@ 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; + _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; + delete _building; + delete _distribution; + delete _direction; + delete _model; + delete _solver; + delete _iod; + delete _em; } /************************************************ @@ -63,7 +63,7 @@ Simulation::~Simulation() { void Simulation::SetPedsNumber(int i) { - _nPeds = i; + _nPeds = i; } @@ -73,436 +73,436 @@ void Simulation::SetPedsNumber(int i) { int Simulation::GetPedsNumber() const { - return _nPeds; + return _nPeds; } Building * Simulation::GetBuilding() const { - return _building; + 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(); + 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 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 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(); + //_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()); - } - } + 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 bb30bd43b80fc7e6ac7def98cdf69d5a9f41524c..4a9287471d94d8b0c11732d6589f66b902ead051 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/events/EventManager.h b/events/EventManager.h index 35a3f7ab9bcd2c8832cc5e6cb4b8439005a0d1aa..f8df1588a719012a24f83ec7a85665b876500431 100644 --- a/events/EventManager.h +++ b/events/EventManager.h @@ -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 111af75cdd4ca8d8adbf14aef4a13d6e05818483..7f97e16c7c087f25a75df491c3279c4d24e47e37 100644 --- a/general/ArgumentParser.cpp +++ b/general/ArgumentParser.cpp @@ -587,7 +587,7 @@ void ArgumentParser::ParseIniFile(string inifile){ //exit crossing strategy if(xPara->FirstChild("exitCrossingStrategy")){ const char* tmp=xPara->FirstChild("exitCrossingStrategy")->FirstChild()->Value(); - if(tmp) pExitStrategy= atoi(tmp); + if(tmp) pExitStrategy= atoi(tmp); Log->Write("INFO: \texitCrossingStrategy < %d >", pExitStrategy); } diff --git a/general/ArgumentParser.h b/general/ArgumentParser.h index 60c68e0fdc2d7940cd3bb18f5258f68e28094597..330cbabfa0fa395e2d650f53c470e2e912e3d866 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 63f372c299283a25e42b7917ecb3a26384784a9b..b5685dbafa618d8727b1b699ad1e079daa443e84 100644 --- a/general/Macros.h +++ b/general/Macros.h @@ -33,7 +33,7 @@ #define _USE_MATH_DEFINES #include <math.h> -#define M_PI 3.14159265358979323846 +#define M_PI 3.14159265358979323846 // should be true only when using this file in the simulation core #define _SIMULATOR 1 @@ -70,33 +70,33 @@ #define FINAL_DEST_OUT -1 // Linked cells -#define LIST_EMPTY -1 +#define LIST_EMPTY -1 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 }; @@ -109,5 +109,5 @@ inline double xmltof(const char * t,double v=0.0){ if (t&&(*t)) return atof(t) 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 */ +#endif /* _MACROS_H */ diff --git a/geometry/Building.cpp b/geometry/Building.cpp index c25824d1a988b2796a64fcbc727bc013d069995b..7c312dda49140b8695463b296ab2d058557c7394 100644 --- a/geometry/Building.cpp +++ b/geometry/Building.cpp @@ -40,8 +40,8 @@ #ifdef _OPENMP #include <omp.h> #else -#define omp_get_thread_num() 0 -#define omp_get_max_threads() 1 +#define omp_get_thread_num() 0 +#define omp_get_max_threads() 1 #endif @@ -52,65 +52,65 @@ using namespace std; ************************************************************/ Building::Building() { - _caption = "no_caption"; - _projectFilename = ""; - _geometryFilename= ""; - _rooms = vector<Room*>(); - _routingEngine = NULL; - _linkedCellGrid = NULL; - _savePathway = false; + _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]; + 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; + _caption = s; } void Building::SetRoutingEngine(RoutingEngine* r) { - _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); - } + if ((index >= 0) && (index < (int) _rooms.size())) { + _rooms[index] = room; + } else { + Log->Write("ERROR: \tWrong Index in CBuilding::SetRoom()"); + exit(0); + } } /************************************************************* @@ -118,694 +118,694 @@ void Building::SetRoom(Room* room, int index) { ************************************************************/ string Building::GetCaption() const { - return _caption; + return _caption; } RoutingEngine* Building::GetRoutingEngine() const { - return _routingEngine; + return _routingEngine; } int Building::GetNumberOfRooms() const { - return _rooms.size(); + return _rooms.size(); } int Building::GetNumberOfGoals() const { - return _transitions.size() + _hLines.size() + _crossings.size(); + return _transitions.size() + _hLines.size() + _crossings.size(); } const vector<Room*>& Building::GetAllRooms() const { - return _rooms; + 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); - } + 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; + return _linkedCellGrid; } void Building::AddRoom(Room* room) { - _rooms.push_back(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); + 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"); + 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; + return _projectFilename; } void Building::SetProjectFilename(const std::string &filename){ - _projectFilename=filename; + _projectFilename=filename; } void Building::SetProjectRootDir(const std::string &filename){ - _projectRootDir= filename; + _projectRootDir= filename; } const string& Building::GetProjectRootDir() const{ - return _projectRootDir; + return _projectRootDir; } const std::string& Building::GetGeometryFilename() const { - return _geometryFilename; + 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"); + //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"); + 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); + 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; + 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; + 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; + 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; + 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; + return _crossings; } const map<int, Transition*>& Building::GetAllTransitions() const { - return _transitions; + return _transitions; } const map<int, Hline*>& Building::GetAllHlines() const { - return _hLines; + return _hLines; } const map<int, Goal*>& Building::GetAllGoals() const { - return _goals; + 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); + //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); - } - } + 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); - } - } + 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; + { + //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; + { + //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; + 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; + 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; + 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"); + 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 @@ -813,374 +813,374 @@ void Building::SanityCheck(){ //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); - } - } - } - } + 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; + // 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(); + { + 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); - } - } - } + 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); + _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 "); + // 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; - } + 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; + } } @@ -1188,318 +1188,318 @@ void Building::DumpSubRoomInRoom(int roomID, int subID) { 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"); + 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"); + 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; + 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; - } - } + 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; + 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); + // 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"); - - } + _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(); - } - - } - } + //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; + 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 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; + //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 a4cde8b5ff1b16a363b23e01c61f28389ce53135..b34af34b49d7fa7428489522176dff2bb6ab509b 100644 --- a/geometry/Building.h +++ b/geometry/Building.h @@ -27,7 +27,7 @@ */ #ifndef _BUILDING_H -#define _BUILDING_H +#define _BUILDING_H #include <string> #include <vector> @@ -49,164 +49,164 @@ 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); }; -#endif /* _BUILDING_H */ +#endif /* _BUILDING_H */ diff --git a/geometry/Crossing.cpp b/geometry/Crossing.cpp index d96317bd9723f61dc4a6ab05b4097b19d3b1d6b0..2e5584494ec8a9a23610246dbc35b7a9249d9d1d 100644 --- a/geometry/Crossing.cpp +++ b/geometry/Crossing.cpp @@ -40,7 +40,7 @@ Crossing::Crossing(){ _room1 = NULL; _subRoom1 = NULL; _subRoom2 = NULL; - _caption = ""; + _caption = ""; } Crossing::~Crossing() { @@ -64,7 +64,7 @@ void Crossing::SetSubRoom2(SubRoom* r2) { } void Crossing::SetCaption(string s) { - _caption = s; + _caption = s; } // Getter-Funktionen @@ -72,7 +72,7 @@ int Crossing::GetID() const { return _id; } string Crossing::GetCaption() const { - return _caption; + return _caption; } Room* Crossing::GetRoom1() const { return _room1; @@ -99,7 +99,7 @@ bool Crossing::IsOpen() const { } bool Crossing::IsTransition() const { - return false; + return false; } @@ -130,8 +130,8 @@ SubRoom* Crossing::GetOtherSubRoom(int roomID, int subroomID) const { 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); + 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; } } @@ -154,7 +154,7 @@ void Crossing::WriteToErrorLog() const { // TraVisTo Ausgabe string Crossing::WriteElement() const { - //return ""; + //return ""; string geometry; char tmp[CLENGTH] = ""; sprintf(tmp,"\t\t<door ID=\"%d\" color = \"250\" caption=\"%d_%d\">\n",GetUniqueID(),GetID(),GetUniqueID()); diff --git a/geometry/Crossing.h b/geometry/Crossing.h index 55db521010604961457bab08714e4a265a9887e8..91f664c112f175f955c919b1d6f2d4f4857f08c8 100644 --- a/geometry/Crossing.h +++ b/geometry/Crossing.h @@ -27,7 +27,7 @@ */ #ifndef _CROSSING_H -#define _CROSSING_H +#define _CROSSING_H #include "NavLine.h" @@ -36,112 +36,112 @@ 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 */ +#endif /* _CROSSING_H */ diff --git a/geometry/Goal.cpp b/geometry/Goal.cpp index 54aecafd0ea8f215f8d5745c798b95456d6b1892..1deff14d7a9ef39c89e875e1a534436d26d6e5ec 100644 --- a/geometry/Goal.cpp +++ b/geometry/Goal.cpp @@ -35,11 +35,11 @@ using namespace std; Goal::Goal() { - _id=-1; - _caption="Goal"; - _isFinalGoal=0; - _walls = vector<Wall > (); - _poly = vector<Point > (); + _id=-1; + _caption="Goal"; + _isFinalGoal=0; + _walls = vector<Wall > (); + _poly = vector<Point > (); } Goal::~Goal() { @@ -47,171 +47,171 @@ Goal::~Goal() { } void Goal::AddWall(const Wall& w) { - _walls.push_back(w); + _walls.push_back(w); } string Goal::GetCaption() const { - return _caption; + return _caption; } void Goal::SetCaption(string caption) { - _caption = caption; + _caption = caption; } int Goal::GetId() const { - return _id; + return _id; } void Goal::SetId(int id) { - _id = id; + _id = id; } const vector<Point>& Goal::GetPolygon() const { - return _poly; + 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 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; + 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); + return (vertex.GetX() > hitPos.GetX()) ? ((vertex.GetY() > hitPos.GetY()) ? 1 : 4) : + ((vertex.GetY() > hitPos.GetY()) ? 2 : 3); } int Goal::GetIsFinalGoal() const { - return _isFinalGoal; + return _isFinalGoal; } void Goal::SetIsFinalGoal(int isFinalGoal) { - _isFinalGoal = 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()))); + 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; + 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(); + 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; + return _centroid; } void Goal::ComputeControid() { diff --git a/geometry/Goal.h b/geometry/Goal.h index 9efec6590455d3e9074ea56d67ce97a467e9e379..609a489819e790c142c9c84f4928cf12b30f1c53 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 1600a95330b770cce308705dac397560bed5e7b9..f215eb2f72e0796c668748bf5cec5abc98f3134b 100644 --- a/geometry/Hline.cpp +++ b/geometry/Hline.cpp @@ -31,52 +31,52 @@ using namespace std; Hline::Hline() { - _room=NULL; - _subRoom=NULL; - _id=-1; + _room=NULL; + _subRoom=NULL; + _id=-1; } Hline::~Hline() { } void Hline::SetID(int ID) { - _id=ID; + _id=ID; } void Hline::SetRoom(Room* r) { - _room=r; + _room=r; } void Hline::SetCaption(string s) { - _caption=s; + _caption=s; } void Hline::SetSubRoom(SubRoom* s) { - _subRoom=s; + _subRoom=s; } int Hline::GetID() const { - return _id; + return _id; } string Hline::GetCaption() const { - return _caption; + return _caption; } Room* Hline::GetRoom() const { - return _room; + return _room; } SubRoom* Hline::GetSubRoom() const { - return _subRoom; + return _subRoom; } bool Hline::IsInSubRoom(int subroomID) const { - return _subRoom->GetSubRoomID() == subroomID; + return _subRoom->GetSubRoomID() == subroomID; } bool Hline::IsInRoom(int roomID) const { - return _room->GetID() == roomID; + return _room->GetID() == roomID; } void Hline::WriteToErrorLog() const { diff --git a/geometry/Hline.h b/geometry/Hline.h index 120b7f0363069de177ea70438a543e4dc807710c..64d33619bf9aa201360238359ac66ec8e96b3a7c 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 f83630bb7d702123af5fb91319177f7abac11c50..1d93e13cb3090d22ced1928d39f73c2811ca4f2f 100644 --- a/geometry/Line.cpp +++ b/geometry/Line.cpp @@ -42,26 +42,26 @@ using namespace std; Konstruktoren ************************************************************/ Line::Line() { - SetPoint1(Point()); //Default-Constructor (0.0,0.0) - SetPoint2(Point()); - _uid = _static_UID++; + 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++; + SetPoint1(p1); + SetPoint2(p2); + _uid = _static_UID++; } int Line::GetUniqueID() const { - return _uid; + return _uid; } Line::Line(const Line& orig) { - _point1 = orig.GetPoint1(); - _point2 = orig.GetPoint2(); - _centre = orig.GetCentre(); - _uid = orig.GetUniqueID(); + _point1 = orig.GetPoint1(); + _point2 = orig.GetPoint2(); + _centre = orig.GetCentre(); + _uid = orig.GetUniqueID(); } Line::~Line() { @@ -71,47 +71,47 @@ Line::~Line() { Setter-Funktionen ************************************************************/ void Line::SetPoint1(const Point& p) { - _point1 = p; - _centre = (_point1+_point2)*0.5; + _point1 = p; + _centre = (_point1+_point2)*0.5; } void Line::SetPoint2(const Point& p) { - _point2 = p; - _centre = (_point1+_point2)*0.5; + _point2 = p; + _centre = (_point1+_point2)*0.5; } /************************************************************* Getter-Funktionen ************************************************************/ const Point& Line::GetPoint1() const { - return _point1; + return _point1; } const Point& Line::GetPoint2() const { - return _point2; + return _point2; } const Point& Line::GetCentre()const { - return _centre; + 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 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; } @@ -121,65 +121,65 @@ 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); + 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(); + // 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; + 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 @@ -188,19 +188,19 @@ Point Line::LotPoint(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 @@ -208,25 +208,25 @@ Point Line::ShortestPoint(const Point& p) const { * lambda berechnen und prüfen ob zwischen 0 und 1 * */ //bool Line::IsInLine(const Point& p) const { -// double ax, ay, bx, by, px, py; -// const Point& a = GetPoint1(); -// const Point& b = GetPoint2(); -// double lambda; -// ax = a.GetX(); -// ay = a.GetY(); -// bx = b.GetX(); -// by = b.GetY(); -// px = p.GetX(); -// py = p.GetY(); -// if (fabs(ax - bx) > J_EPS_DIST) { -// lambda = (px - ax) / (bx - ax); -// } else if (fabs(ay - by) > J_EPS_DIST) { -// lambda = (py - ay) / (by - ay); -// } else { -// Log->Write("ERROR: \tIsInLine: Endpunkt = Startpunkt!!!"); -// exit(0); -// } -// return (0 <= lambda) && (lambda <= 1); +// double ax, ay, bx, by, px, py; +// const Point& a = GetPoint1(); +// const Point& b = GetPoint2(); +// double lambda; +// ax = a.GetX(); +// ay = a.GetY(); +// bx = b.GetX(); +// by = b.GetY(); +// px = p.GetX(); +// py = p.GetY(); +// if (fabs(ax - bx) > J_EPS_DIST) { +// lambda = (px - ax) / (bx - ax); +// } else if (fabs(ay - by) > J_EPS_DIST) { +// lambda = (py - ay) / (by - ay); +// } else { +// Log->Write("ERROR: \tIsInLine: Endpunkt = Startpunkt!!!"); +// exit(0); +// } +// return (0 <= lambda) && (lambda <= 1); //} /* @@ -235,25 +235,25 @@ Point Line::ShortestPoint(const Point& p) const { * 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; - + //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 @@ -261,16 +261,16 @@ bool Line::IsInLineSegment(const Point& p) const { * benuzt * */ double Line::DistTo(const Point& p) const { - return (p - ShortestPoint(p)).Norm(); + return (p - ShortestPoint(p)).Norm(); } double Line::DistToSquare(const Point& p) const { - return (p - ShortestPoint(p)).NormSquare(); + return (p - ShortestPoint(p)).NormSquare(); } // bool Line::operator*(const Line& l) const { -// return ((_point1*l.GetPoint1() && _point2 == l.GetPoint2()) || -// (_point2 == l.GetPoint1() && _point1 == l.GetPoint2())); +// return ((_point1*l.GetPoint1() && _point2 == l.GetPoint2()) || +// (_point2 == l.GetPoint1() && _point1 == l.GetPoint2())); // } @@ -278,197 +278,197 @@ double Line::DistToSquare(const Point& p) const { * gleich sind * */ bool Line::operator==(const Line& l) const { - return ((_point1 == l.GetPoint1() && _point2 == l.GetPoint2()) || - (_point2 == l.GetPoint1() && _point1 == l.GetPoint2())); + 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())); + return ((_point1 != l.GetPoint1() && _point2 != l.GetPoint2()) && + (_point2 != l.GetPoint1() && _point1 != l.GetPoint2())); } double Line::Length() const { - return (_point1 - _point2).Norm(); + return (_point1 - _point2).Norm(); } double Line::LengthSquare() const { - return (_point1 - _point2).NormSquare(); + return (_point1 - _point2).NormSquare(); } 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; + return fabs (_point1._y-_point2._y ) <= J_EPS; } bool Line::IsVertical(){ - return fabs (_point1._x-_point2._x ) <= J_EPS; + 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; - } + //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; + 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; + if (_point1==point) return true; + if (_point2==point) return true; + return false; } 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; + 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; - } + if (IsLeft(pt)){ + return _point2; + }else{ + return _point1; + } } const Point& Line::GetRight(const Point& pt){ - if (!IsLeft(pt)){ - return _point2; - }else{ - return _point1; - } + if (!IsLeft(pt)){ + return _point2; + }else{ + return _point1; + } } std::string Line::toString() const { - std::stringstream tmp; - tmp<<_point1.toString()<<"--"<<_point2.toString(); - return tmp.str(); + 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 @@ -476,50 +476,50 @@ std::string Line::toString() const { //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 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; double infinity =100000; - // 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()) || + // the segment are superposed + if(IsInLineSegment(l.GetPoint1()) || IsInLineSegment(l.GetPoint2()) ) return infinity;//really? - else return infinity; + else return infinity; - } 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 infinity; - } - } + } + } - // the lines intersect - double r = numerator / denominator; - if (r < 0.0 || r > 1.0) { - 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; - } + 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)); + 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<< " 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; + return dist; } //sign of the angle depends on the direction of the wall (l). diff --git a/geometry/Line.h b/geometry/Line.h index 9ad40024cefb805f0eb1afa0a38767cf634a2f26..1b43fe5da45ef9f526cc6b2ef6c1ec52d37a2b4a 100644 --- a/geometry/Line.h +++ b/geometry/Line.h @@ -26,7 +26,7 @@ */ #ifndef _LINE_H -#define _LINE_H +#define _LINE_H #include "Point.h" //#include "SubRoom.h" @@ -40,200 +40,200 @@ 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; + 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; + /** + * @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; }; -#endif /* _LINE_H */ +#endif /* _LINE_H */ diff --git a/geometry/NavLine.h b/geometry/NavLine.h index 442ffa8b919d367945d78c01e6f55b8a292c6fda..205a63ec5e84270a360f22199c57ef6bd7578fe7 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 89eecf0c0861ce881c9f177843d9599edc26d12f..e2760d141c57931c86d9f95f907ed446c81f9589 100644 --- a/geometry/Obstacle.cpp +++ b/geometry/Obstacle.cpp @@ -45,199 +45,199 @@ using namespace std; Obstacle::Obstacle() { - _isClosed=0.0; - _height=0.0; - _id=-1; - _caption="obstacle"; - _walls = vector<Wall > (); - _poly = vector<Point > (); + _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); + _walls.push_back(w); } string Obstacle::GetCaption() const { - return _caption; + return _caption; } void Obstacle::SetCaption(string caption) { - _caption = caption; + _caption = caption; } double Obstacle::GetClosed() const { - return _isClosed; + return _isClosed; } void Obstacle::SetClosed(double closed) { - _isClosed = closed; + _isClosed = closed; } double Obstacle::GetHeight() const { - return _height; + return _height; } void Obstacle::SetHeight(double height) { - _height = height; + _height = height; } int Obstacle::GetId() const { - return _id; + return _id; } void Obstacle::SetId(int id) { - _id = id; + _id = id; } const vector<Point>& Obstacle::GetPolygon() const { - return _poly; + return _poly; } string Obstacle::Write() { - string s; - //Point pos; + 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; + 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); + 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()))); + 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; + // 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; + 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{ @@ -284,10 +284,10 @@ const Point Obstacle::GetCentroid() 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 79d3ed2c74946927865b0de849ef4804168ab4e5..7a397f034876a8203a36d2c1ba3b34003af660d4 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 3f7256225da035635d0d774325461fce55fa8f0f..4ebaf4b28df993f554b4bfc665566de28ba876c5 100644 --- a/geometry/Point.cpp +++ b/geometry/Point.cpp @@ -54,9 +54,9 @@ Point::Point(const Point& orig) { } std::string Point::toString() const { - std::stringstream tmp; - tmp<<"( "<<_x<<" : " <<_y<<" )"; - return tmp.str(); + std::stringstream tmp; + tmp<<"( "<<_x<<" : " <<_y<<" )"; + return tmp.str(); }; void Point::SetX(double x) { @@ -98,7 +98,7 @@ double Point::ScalarP(const Point& v) const { /// 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; + return _x * v._y - _y * v._x; } /* Transformiert die "normalen" Koordinaten in Koordinaten der Ellipse diff --git a/geometry/Point.h b/geometry/Point.h index 46dcca7b19c4f4afc22d433b237c8f6461af361e..d3ee34ce10c9d06e87efe024193810d401ce63bc 100644 --- a/geometry/Point.h +++ b/geometry/Point.h @@ -26,72 +26,72 @@ */ #ifndef _POINT_H -#define _POINT_H +#define _POINT_H #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 @@ -99,5 +99,5 @@ const Point operator*(const Point& p, const double f); /// division const Point operator/(const Point& p, const double f); -#endif /* _POINT_H */ +#endif /* _POINT_H */ diff --git a/geometry/Room.cpp b/geometry/Room.cpp index 1f58769e8ab866023f20fbe4e9cf279997821a07..1f9fa66b8cbf492a4de225700084c3e78e198c7a 100644 --- a/geometry/Room.cpp +++ b/geometry/Room.cpp @@ -82,7 +82,7 @@ void Room::SetSubRoom(SubRoom* subroom, int index) { } void Room::SetState(RoomState state) { - _state=state; + _state=state; } @@ -99,7 +99,7 @@ string Room::GetCaption() const { double Room::GetZPos() const { //if(pCaption=="070") return pZPos+1.0; - return _zPos; + return _zPos; } int Room::GetNumberOfSubRooms() const { @@ -114,7 +114,7 @@ SubRoom* Room::GetSubRoom(int index) const { if ((index >= 0) && (index < (int) _subRooms.size())) return _subRooms[index]; else { - char tmp[CLENGTH]; + char tmp[CLENGTH]; sprintf(tmp,"ERROR: Room::GetSubRoom() Wrong subroom index [%d] for room index [%d] ",index,_id); Log->Write(tmp); exit(EXIT_FAILURE); @@ -135,7 +135,7 @@ int Room::GetNumberOfPedestrians() const { #endif // _SIMULATOR RoomState Room::GetState() const { - return _state; + return _state; } @@ -176,17 +176,17 @@ void Room::WriteToErrorLog() const { } const vector<int>& Room::GetAllTransitionsIDs() const { - return _transitionsIDs; + return _transitionsIDs; } void Room::AddTransitionID(int ID){ - _transitionsIDs.push_back(ID); + _transitionsIDs.push_back(ID); } void Room::SetOutputHandler(OutputHandler* oh){ - _outputFile=oh; + _outputFile=oh; } OutputHandler* Room::GetOutputHandler() const { - return _outputFile; + return _outputFile; } diff --git a/geometry/Room.h b/geometry/Room.h index 7917089bc9899b8a92036f9c140313c95fd31be5..19a038113beea115db2d06ef3a8e08655fd44f0b 100644 --- a/geometry/Room.h +++ b/geometry/Room.h @@ -24,7 +24,7 @@ */ #ifndef _ROOM_H -#define _ROOM_H +#define _ROOM_H #include <string> #include <algorithm> @@ -33,131 +33,131 @@ //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; }; -#endif /* _ROOM_H */ +#endif /* _ROOM_H */ diff --git a/geometry/SubRoom.cpp b/geometry/SubRoom.cpp index 4ad68da46ad2f09ee9822b780bbaa82e029bf0c1..e7196269ba5613ea26d77f231e94a829e17ec2c2 100644 --- a/geometry/SubRoom.cpp +++ b/geometry/SubRoom.cpp @@ -47,60 +47,60 @@ 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++; + _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(); + _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(); + 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 } @@ -108,268 +108,268 @@ SubRoom::~SubRoom() { // Setter -Funktionen void SubRoom::SetSubRoomID(int ID) { - _id = ID; + _id = ID; } void SubRoom::SetClosed(double closed) { - _closed = closed; + _closed = closed; } void SubRoom::SetRoomID(int ID) { - _roomID = ID; + _roomID = ID; } int SubRoom::GetSubRoomID() const { - return _id; + return _id; } double SubRoom::GetClosed() const { - return _closed; + return _closed; } // unique identifier for this subroom int SubRoom::GetUID() const { - return _uid; - //return pRoomID * 1000 + pID; + return _uid; + //return pRoomID * 1000 + pID; } double SubRoom::GetArea() const { - return _area; + return _area; } int SubRoom::GetRoomID() const { - return _roomID; + return _roomID; } int SubRoom::GetNumberOfWalls() const { - return _walls.size(); + return _walls.size(); } const vector<Wall>& SubRoom::GetAllWalls() const { - return _walls; + 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); - } + 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; + return _poly; } const vector<Obstacle*>& SubRoom::GetAllObstacles() const { - return _obstacles; + return _obstacles; } int SubRoom::GetNumberOfGoalIDs() const { - return _goalIDs.size(); + return _goalIDs.size(); } const vector<int>& SubRoom::GetAllGoalIDs() const { - return _goalIDs; + return _goalIDs; } // Sonstiges void SubRoom::AddWall(const Wall& w) { - _walls.push_back(w); + _walls.push_back(w); } void SubRoom::AddObstacle(Obstacle* obs){ - _obstacles.push_back(obs); - CheckObstacles(); + _obstacles.push_back(obs); + CheckObstacles(); } void SubRoom::AddGoalID(int ID) { - _goalIDs.push_back(ID); + _goalIDs.push_back(ID); } void SubRoom::AddCrossing(Crossing* line){ - _crossings.push_back(line); - _goalIDs.push_back(line->GetUniqueID()); + _crossings.push_back(line); + _goalIDs.push_back(line->GetUniqueID()); } void SubRoom::AddTransition(Transition* line){ - _transitions.push_back(line); - _goalIDs.push_back(line->GetUniqueID()); + _transitions.push_back(line); + _goalIDs.push_back(line->GetUniqueID()); } void SubRoom::AddHline(Hline* line){ - _hlines.push_back(line); - _goalIDs.push_back(line->GetUniqueID()); + _hlines.push_back(line); + _goalIDs.push_back(line->GetUniqueID()); } const vector<Crossing*>& SubRoom::GetAllCrossings() const{ - return _crossings; + return _crossings; } const vector<Transition*>& SubRoom::GetAllTransitions() const{ - return _transitions; + return _transitions; } const vector<Hline*>& SubRoom::GetAllHlines() const{ - return _hlines; + return _hlines; } const Crossing* SubRoom::GetCrossing(int i) const { - return _crossings[i]; + return _crossings[i]; } const Transition* SubRoom::GetTransition(int i) const { - return _transitions[i]; + return _transitions[i]; } const Hline* SubRoom::GetHline(int i) const { - return _hlines[i]; + 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"); + 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)); + 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); - - 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; - } - - - //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; + // 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]; + // 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]; } @@ -378,140 +378,140 @@ bool SubRoom::IsVisible(Line* l1, Line* l2, bool considerHlines) // 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; + //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)); + _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; + return _planeEquation; } double SubRoom::GetElevation(const Point& p) const { - return _planeEquation[0] * p._x + _planeEquation[1] * p._y + _planeEquation[2]; + return _planeEquation[0] * p._x + _planeEquation[1] * p._y + _planeEquation[2]; } double SubRoom::GetCosAngleWithHorizontal() const { - return _cosAngleWithHorizontalPlane; + 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); - } - } - } + 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 - } - } + 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; + 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); - } + 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 ); } @@ -530,115 +530,115 @@ 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 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]; + 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"); + 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()); - } + //write the obstacles + for( unsigned int j=0;j<GetAllObstacles().size(); j++) { + s.append(GetAllObstacles()[j]->Write()); + } - return s; + 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(); - } + 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; + 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; } @@ -647,64 +647,64 @@ 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); + 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()))); + 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; + 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; } /************************************************************ @@ -712,13 +712,13 @@ bool NormalSubRoom::IsInSubRoom(const Point& ped) const { ************************************************************/ Stair::Stair() : NormalSubRoom() { - pUp = Point(); - pDown = Point(); + pUp = Point(); + pDown = Point(); } Stair::Stair(const Stair & orig) : NormalSubRoom(orig) { - pUp = orig.GetUp(); - pDown = orig.GetDown(); + pUp = orig.GetUp(); + pDown = orig.GetDown(); } Stair::~Stair() { @@ -727,88 +727,88 @@ Stair::~Stair() { // Setter-Funktionen void Stair::SetUp(const Point & p) { - pUp = p; + pUp = p; } void Stair::SetDown(const Point & p) { - pDown = p; + pDown = p; } // Getter-Funktionen const Point & Stair::GetUp() const { - return pUp; + return pUp; } const Point & Stair::GetDown() const { - return pDown; + return pDown; } 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 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 s; - char tmp[CLENGTH]; + 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"); + 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()); - } + //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(); - } + Log->Write("\t\tStair:\n"); + for (int i = 0; i < GetNumberOfWalls(); i++) { + Wall w = GetWall(i); + w.WriteToErrorLog(); + } } /* prüft ob die Punkte p1, p2 und p3 auf einer Linie liegen, oder eine Ecke bilden. @@ -816,203 +816,203 @@ void Stair::WriteToErrorLog() const { * */ 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; + 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" + //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; + 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; + 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; + 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; + return rueck; } void SubRoom::SetType(const std::string& type) { - _type = type; + _type = type; } const std::string& SubRoom::GetType() const { - return _type; + return _type; } #ifdef _SIMULATOR void SubRoom::SetAllPedestrians(const vector<Pedestrian*>& peds) { - _peds = 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); - } + 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); + //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(); + return _peds.size(); } const vector<Pedestrian*>& SubRoom::GetAllPedestrians() const { - return _peds; + 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); - } + 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); + _peds.push_back(ped); } void SubRoom::DeletePedestrian(int index) { - if ((index >= 0) && (index < (int) GetNumberOfPedestrians())) { - _peds.erase(_peds.begin() + 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(); + 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 5fc028546cc38131f328cbf5a53539700dba6b78..6cacfcf6035528ca736b87c2a9101ab2ff931b9e 100644 --- a/geometry/SubRoom.h +++ b/geometry/SubRoom.h @@ -26,7 +26,7 @@ */ #ifndef _SUBROOM_H -#define _SUBROOM_H +#define _SUBROOM_H #include "Line.h" @@ -41,293 +41,293 @@ class Obstacle; class Crossing; #ifdef _SIMULATOR - class Pedestrian; +class Pedestrian; #endif /************************************************************ SubRoom - ************************************************************/ +************************************************************/ 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 @@ -335,62 +335,62 @@ public: /************************************************************ NormalSubroom - ************************************************************/ +************************************************************/ 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; }; /************************************************************ Stair - ************************************************************/ +************************************************************/ 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 */ +#endif /* _SUBROOM_H */ diff --git a/geometry/Transition.cpp b/geometry/Transition.cpp index 92ce074ba9e40faf08d6e245c9867aeafd573267..a22265d8b5a00917c920c35c699a7c365badda7e 100644 --- a/geometry/Transition.cpp +++ b/geometry/Transition.cpp @@ -36,10 +36,10 @@ using namespace std; ************************************************************/ Transition::Transition() : Crossing() { - _isOpen = true; - _doorUsage=0; - _lastPassingTime=0; - _room2 = NULL; + _isOpen = true; + _doorUsage=0; + _lastPassingTime=0; + _room2 = NULL; } Transition::~Transition() { @@ -48,73 +48,73 @@ Transition::~Transition() { // Setter-Funktionen void Transition::Close() { - _isOpen = false; + _isOpen = false; } void Transition::Open() { - _isOpen = true; + _isOpen = true; } void Transition::SetType(string type){ - _type=type; + _type=type; } void Transition::SetRoom2(Room* r) { - _room2 = r; + _room2 = r; } // Getter-Funktionen bool Transition::IsOpen() const { - return _isOpen; + return _isOpen; } Room* Transition::GetRoom2() const { - return _room2; + return _room2; } string Transition::GetType() const { - return _type; + 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); - } + 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; + 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 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; + return true; } @@ -122,74 +122,74 @@ bool Transition::IsTransition() const { * 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); - } + 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); + 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; + 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; + _doorUsage+=number; + _lastPassingTime=time; } int Transition::GetDoorUsage() const { - return _doorUsage; + return _doorUsage; } double Transition::GetLastPassingTime() const { - return _lastPassingTime; + return _lastPassingTime; } diff --git a/geometry/Transition.h b/geometry/Transition.h index 85d1ca9fb208943542b7971e2cffdd298c29e5f1..825c97da33f9a5677b7287d82b83d8dfe48ea00f 100644 --- a/geometry/Transition.h +++ b/geometry/Transition.h @@ -25,7 +25,7 @@ */ #ifndef _TRANSITION_H -#define _TRANSITION_H +#define _TRANSITION_H #include "Crossing.h" #include <string> @@ -34,87 +34,87 @@ 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 */ +#endif /* _TRANSITION_H */ diff --git a/geometry/Wall.h b/geometry/Wall.h index 85e2ba51ee11a6bd166f5f0f7c7d5e79f93e3a0c..a1cf286095a50cd14a3b03e311780fd3f2da4fa8 100644 --- a/geometry/Wall.h +++ b/geometry/Wall.h @@ -26,28 +26,28 @@ */ #ifndef _WALL_H -#define _WALL_H +#define _WALL_H #include "Line.h" class Wall : public Line { -public: - Wall(); - Wall(const Point& p1, const Point& p2); - Wall(const Wall& orig); + public: + Wall(); + Wall(const Point& p1, const Point& p2); + Wall(const Wall& orig); - /** - * Debug output from the object - */ - void WriteToErrorLog() const; + /** + * Debug output from the object + */ + void WriteToErrorLog() const; - /** - * @return a nicely formated string of the object - */ - virtual std::string Write() const; + /** + * @return a nicely formated string of the object + */ + virtual std::string Write() const; }; -#endif /* _WALL_H */ +#endif /* _WALL_H */ diff --git a/main.cpp b/main.cpp index 5f8ba4241e38ae396c7f0fcb417b75965f18945b..0096e7d0fe2de96b5681059e062f710d90760083 100644 --- a/main.cpp +++ b/main.cpp @@ -32,14 +32,14 @@ * * JuPedSim stands for Jülich Pedestrians Simulator and is currently developed at the Forschungszentrum Jülich in Germany. * - * + * * * Some useful links: * - * 1: <A HREF="http://www.openpedsim.org">www.openpedsim.org</A> <BR> - * 2: <a href="http://www.vtk.org">www.vtk.org</a> <br> - * 3: <a href="http://www.fz-juelich.de">www.fz-juelich.de</a> <br> - * 4: <a href="http://www.jupedsim.org">www.fz-juelich.de</a> <br> + * 1: <A HREF="http://www.openpedsim.org">www.openpedsim.org</A> <BR> + * 2: <a href="http://www.vtk.org">www.vtk.org</a> <br> + * 3: <a href="http://www.fz-juelich.de">www.fz-juelich.de</a> <br> + * 4: <a href="http://www.jupedsim.org">www.fz-juelich.de</a> <br> * */ @@ -53,51 +53,49 @@ OutputHandler* Log; int main(int argc, char **argv) { - time_t starttime, endtime; - + time_t starttime, endtime; - //Log = new FileHandler("./Logfile.dat"); - Log = new STDIOHandler(); - // Parsing the arguments - ArgumentParser* args = new ArgumentParser(); - args->ParseArgs(argc, argv); + //Log = new FileHandler("./Logfile.dat"); + Log = new STDIOHandler(); - // create and init the simulation engine - // Simulation - time(&starttime); - Log->Write("INFO: \tStart runSimulation()\n"); + // Parsing the arguments + ArgumentParser* args = new ArgumentParser(); + args->ParseArgs(argc, argv); - + // create and init the simulation engine + // Simulation + time(&starttime); + Log->Write("INFO: \tStart runSimulation()\n"); - Simulation sim = Simulation(); - sim.InitArgs(args); - int evacTime = sim.RunSimulation(); - Log->Write("\nINFO: \tEnd runSimulation()\n"); - time(&endtime); + Simulation sim = Simulation(); + sim.InitArgs(args); + int evacTime = sim.RunSimulation(); + Log->Write("\nINFO: \tEnd runSimulation()\n"); + time(&endtime); - //some output - double execTime = difftime(endtime, starttime); + //some output + double execTime = difftime(endtime, starttime); - if(sim.GetPedsNumber()) - Log->Write("\nPedestrians not evacuated [%d] using [%d] threads", sim.GetPedsNumber(), - args->GetMaxOpenMPThreads()); + if(sim.GetPedsNumber()) + Log->Write("\nPedestrians not evacuated [%d] using [%d] threads", sim.GetPedsNumber(), + args->GetMaxOpenMPThreads()); - Log->Write("\nExec Time [s] : %.2f", execTime); - Log->Write("Evac Time [s] : %d", evacTime); - Log->Write("Real Time Factor : %.2f X", evacTime / execTime); + Log->Write("\nExec Time [s] : %.2f", execTime); + Log->Write("Evac Time [s] : %d", evacTime); + Log->Write("Real Time Factor : %.2f X", evacTime / execTime); - //sim.PrintStatistics(); + //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); - } + 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.h b/math/Distribution.h index 33a464ada3a39d77c48a353499b740bb6219dbf9..3ffc4fbc0872a5e9b6429df446cad129ae243081 100644 --- a/math/Distribution.h +++ b/math/Distribution.h @@ -26,73 +26,73 @@ */ #ifndef _DISTRIBUTION_H -#define _DISTRIBUTION_H +#define _DISTRIBUTION_H #include <vector> 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 */ +#endif /* _DISTRIBUTION_H */ diff --git a/math/ForceModel.cpp b/math/ForceModel.cpp index d5bf4352996c2925d9b20eaf470373f53d40e16d..0c2964f6583cd94c28089ca2552417c6e4bd8305 100644 --- a/math/ForceModel.cpp +++ b/math/ForceModel.cpp @@ -55,144 +55,144 @@ 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); + 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); + 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(); + } 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; + 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 + 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(); + 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; + } 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 @@ -204,71 +204,71 @@ Point GCFMModel::ForceRepPed(Pedestrian* ped1, Pedestrian* ped2) const { * */ inline Point GCFMModel::ForceRepRoom(Pedestrian* ped, SubRoom* subroom) const { - Point f = Point(0., 0.); - //first the walls + Point f = Point(0., 0.); + //first the walls - const vector<Wall>& walls = subroom->GetAllWalls(); - for (int i = 0; i < subroom->GetNumberOfWalls(); i++) { + 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; + } + + //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 + 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) + 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 + //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 @@ -282,101 +282,101 @@ inline Point GCFMModel::ForceRepWall(Pedestrian* ped, const Wall& w) const { * */ //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 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 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; } @@ -387,65 +387,65 @@ GCFMModel::~GCFMModel(void) { // Getter-Funktionen DirectionStrategy* GCFMModel::GetDirection() const { - return _direction; + return _direction; } double GCFMModel::GetNuPed() const { - return _nuPed; + return _nuPed; } double GCFMModel::GetNuWall() const { - return _nuWall; + return _nuWall; } double GCFMModel::GetIntpWidthPed() const { - return _intp_widthPed; + return _intp_widthPed; } double GCFMModel::GetIntpWidthWall() const { - return _intp_widthWall; + return _intp_widthWall; } double GCFMModel::GetMaxFPed() const { - return _maxfPed; + return _maxfPed; } double GCFMModel::GetMaxFWall() const { - return _maxfWall; + return _maxfWall; } double GCFMModel::GetDistEffMaxPed() const { - return _distEffMaxPed; + return _distEffMaxPed; } double GCFMModel::GetDistEffMaxWall() const { - return _distEffMaxWall; + 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 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); } /** @@ -453,118 +453,118 @@ void GCFMModel::CalculateForce(double time, vector< Point >& result_acc, Buildin */ 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(); + 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); + { + 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]; + 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); + 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); + 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 { -// const vector< Pedestrian* >& allPeds = building->GetAllPedestrians(); +// const vector< Pedestrian* >& allPeds = building->GetAllPedestrians(); // } @@ -1004,12 +1004,12 @@ void GompertzModel::CalculateForceLC(double time, double tip1, Building* buildin }//end parallel } string GompertzModel::writeParameter() const { - string rueck; - char tmp[CLENGTH]; + string rueck; + char tmp[CLENGTH]; - sprintf(tmp, "\t\tNu: \t\tPed: %f \tWall: %f\n", _nuPed, _nuWall); - rueck.append(tmp); - return rueck; + sprintf(tmp, "\t\tNu: \t\tPed: %f \tWall: %f\n", _nuPed, _nuWall); + rueck.append(tmp); + return rueck; } DirectionStrategy* GompertzModel::GetDirection() const { return _direction;} @@ -1018,16 +1018,16 @@ double GompertzModel::GetNuPed() const {return _nuPed;} double GompertzModel::GetNuWall() const {return _nuWall;} GompertzModel::GompertzModel(DirectionStrategy* dir, double nuped, double nuwall) { - _direction = dir; - _nuPed = nuped; - _nuWall = 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 de2092af5e15d4a4b02c7803a9a844bf98570a5d..b3bd8368fb021db9f364e149d57cee6a6a107b57 100644 --- a/math/ForceModel.h +++ b/math/ForceModel.h @@ -30,7 +30,7 @@ // #ifndef _FORCEMODEL_H -#define _FORCEMODEL_H +#define _FORCEMODEL_H #include <vector> @@ -52,31 +52,31 @@ class DirectionStrategy; */ 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; }; /************************************************************ GCFM ForceModel - ************************************************************/ +************************************************************/ /** * @date Fri Apr 18 16:39:13 2014 * @@ -85,83 +85,83 @@ public: * */ 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, + 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); + 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 * @@ -169,88 +169,88 @@ public: * @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; + private: + /// define the strategy for crossing a door (used for calculating the driving force) + DirectionStrategy* _direction; - /// Modellparameter - double _nuPed; - double _nuWall; + /// 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; + /** + * 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: + public: - GompertzModel(DirectionStrategy* dir, double nuped, double nuwall); - virtual ~GompertzModel(void); + 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 */ +#endif /* _FORCEMODEL_H */ diff --git a/math/Mathematics.cpp b/math/Mathematics.cpp index 8432ae8a24c69467013322335cab2d50fabd0892..419854febca1e0a2c3688c9617b01a88da6d9805 100644 --- a/math/Mathematics.cpp +++ b/math/Mathematics.cpp @@ -21,7 +21,7 @@ * * @section DESCRIPTION * - * This class is used to define mathematical parameters, constants and functions. + * This class is used to define mathematical parameters, constants and functions. * * */ @@ -138,20 +138,20 @@ 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; + 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; } ///////////////////////////////////////////////////////////////////////////// diff --git a/math/Mathematics.h b/math/Mathematics.h index 1f574fb6603bc34dc35e68e3ae54a0e1266680dc..32ed7e82b306849bf6e7d1d88199b37d722527fe 100644 --- a/math/Mathematics.h +++ b/math/Mathematics.h @@ -21,7 +21,7 @@ * * @section DESCRIPTION * - * This class is used to define mathematical parameters, constants and functions. + * This class is used to define mathematical parameters, constants and functions. * * */ @@ -35,7 +35,7 @@ double sign(double x); double hermite_interp(double x, double x1, double x2, double y1, double y2, - double dy1, double dy2); + double dy1, double dy2); std::complex<double> c_cbrt(std::complex<double> x); diff --git a/math/ODESolver.h b/math/ODESolver.h index 19ff8c853da9308af546fc84e8916c5c1d6307b7..9d3b5fec57c649561803165cf15f1f8a22d55ab6 100644 --- a/math/ODESolver.h +++ b/math/ODESolver.h @@ -26,7 +26,7 @@ */ #ifndef _ODESOLVER_H -#define _ODESOLVER_H +#define _ODESOLVER_H //forward declarations @@ -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 @@ public: * 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,28 +61,28 @@ public: * 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; }; -#endif /* _ODESOLVER_H */ +#endif /* _ODESOLVER_H */ diff --git a/mpi/LCGrid.cpp b/mpi/LCGrid.cpp index ab7b0e06116e7b3d5e221525f06b9fb439b4c10d..1b4cc70816e27c3ddfe453d003b94dfa613ac725 100644 --- a/mpi/LCGrid.cpp +++ b/mpi/LCGrid.cpp @@ -47,245 +47,245 @@ using namespace std; 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; + 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){ - 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; - } + 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){ - 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; - } - } - - for(int i=0;i<pNpeds;i++) pList[i]=LIST_EMPTY; + // 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; } 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]; - } - } - } + 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]; - } - } - } + 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]; - } - } - } + 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"); - } - } + 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"); - } - } + 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 1018d357377cc7e44d676e0b380aec5adb2c8e00..4e00d8c84acfb2e8bfd2cbb47a9d326ecaea03b3 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 9c51207d8aca2c1c4a6268b5536fc949d114102a..f45b95ff662e7054e96c4e8ac8d894191aa01a5b 100644 --- a/pedestrian/Ellipse.cpp +++ b/pedestrian/Ellipse.cpp @@ -27,7 +27,7 @@ #define _USE_MATH_DEFINES #include <math.h> -#define M_PI 3.14159265358979323846 +#define M_PI 3.14159265358979323846 using namespace std; @@ -38,29 +38,29 @@ using namespace std; ************************************************************/ 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 + _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 + _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 } @@ -69,43 +69,43 @@ JEllipse::JEllipse(const JEllipse& orig) { ************************************************************/ void JEllipse::SetV(const Point& v) { - _vel = v; + _vel = v; } void JEllipse::SetCenter(Point pos) { - _center = pos; + _center = pos; } void JEllipse::SetCosPhi(double c) { - _cosPhi = c; + _cosPhi = c; } void JEllipse::SetSinPhi(double s) { - _sinPhi = s; + _sinPhi = s; } void JEllipse::SetXp(double xp) { - _Xp = xp; + _Xp = xp; } void JEllipse::SetAmin(double a_min) { - _Amin = a_min; + _Amin = a_min; } void JEllipse::SetAv(double a_v) { - _Av = a_v; + _Av = a_v; } void JEllipse::SetBmin(double b_min) { - _Bmin = b_min; + _Bmin = b_min; } void JEllipse::SetBmax(double b_max) { - _Bmax = b_max; + _Bmax = b_max; } void JEllipse::SetV0(double v0) { - __vel0 = v0; + __vel0 = v0; } /************************************************************* @@ -113,61 +113,61 @@ void JEllipse::SetV0(double v0) { ************************************************************/ const Point& JEllipse::GetV() const { - return _vel; + return _vel; } const Point& JEllipse::GetCenter() const { - return _center; + return _center; } double JEllipse::GetCosPhi() const { - return _cosPhi; + return _cosPhi; } double JEllipse::GetSinPhi() const { - return _sinPhi; + return _sinPhi; } double JEllipse::GetXp() const { - return _Xp; + return _Xp; } double JEllipse::GetAmin() const { - return _Amin; + return _Amin; } double JEllipse::GetAv() const { - return _Av; + return _Av; } double JEllipse::GetBmin() const { - return _Bmin; + return _Bmin; } double JEllipse::GetBmax() const { - return _Bmax; + return _Bmax; } double JEllipse::GetV0() const { - return __vel0; + 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 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 x = (_Bmax - _Bmin) / __vel0; + return _Bmax - _vel.Norm() * x; } @@ -194,32 +194,32 @@ double JEllipse::GetEB() const { * */ // double JEllipse::EffectiveDistanceToEllipse(const JEllipse& E2, double* dist) const { -// // E1 ist Objekt auf dem aufgerufen wird -// Point AP1inE1 = Point(this->GetXp(), 0); //Koords in E1 -// Point AP2inE2 = Point(E2.GetXp(), 0); //Koords in E2 -// Point AP1inE2, AP2inE1; - -// // "normale" Koordinaten -// Point R1, R2; -// Point AP1, AP2; -// // Koordinaten transformieren -// AP1 = AP1inE1.CoordTransToCart(this->GetCenter(), this->GetCosPhi(), -// this->GetSinPhi()); -// AP2 = AP2inE2.CoordTransToCart(E2.GetCenter(), E2.GetCosPhi(), -// E2.GetSinPhi()); -// AP1inE2 = AP1.CoordTransToEllipse(E2.GetCenter(), E2.GetCosPhi(), -// E2.GetSinPhi()); -// AP2inE1 = AP2.CoordTransToEllipse(this->GetCenter(), this->GetCosPhi(), -// this->GetSinPhi()); - -// // Abstand zwischen den beiden Actionpoints -// *dist = (AP1 - AP2).Norm(); -// /* fuer E1: Berechnung R1 */ -// R1 = this->PointOnEllipse(AP2inE1); // kuerzester Schnittpunkt E1 mit Gerade durch AP2 von E2 -// /* fuer E2: Berechung R2 */ -// R2 = E2.PointOnEllipse(AP1inE2); // kuerzester Schnittpunkt E2 mit Gerade durch AP1 von E1 -// // Abstand zwischen den beiden Ellipsen -// return (AP1 - AP2).Norm() - (AP1 - R1).Norm() - (AP2 - R2).Norm(); // negative Werte sind bei Überlappung möglich +// // E1 ist Objekt auf dem aufgerufen wird +// Point AP1inE1 = Point(this->GetXp(), 0); //Koords in E1 +// Point AP2inE2 = Point(E2.GetXp(), 0); //Koords in E2 +// Point AP1inE2, AP2inE1; + +// // "normale" Koordinaten +// Point R1, R2; +// Point AP1, AP2; +// // Koordinaten transformieren +// AP1 = AP1inE1.CoordTransToCart(this->GetCenter(), this->GetCosPhi(), +// this->GetSinPhi()); +// AP2 = AP2inE2.CoordTransToCart(E2.GetCenter(), E2.GetCosPhi(), +// E2.GetSinPhi()); +// AP1inE2 = AP1.CoordTransToEllipse(E2.GetCenter(), E2.GetCosPhi(), +// E2.GetSinPhi()); +// AP2inE1 = AP2.CoordTransToEllipse(this->GetCenter(), this->GetCosPhi(), +// this->GetSinPhi()); + +// // Abstand zwischen den beiden Actionpoints +// *dist = (AP1 - AP2).Norm(); +// /* fuer E1: Berechnung R1 */ +// R1 = this->PointOnEllipse(AP2inE1); // kuerzester Schnittpunkt E1 mit Gerade durch AP2 von E2 +// /* fuer E2: Berechung R2 */ +// R2 = E2.PointOnEllipse(AP1inE2); // kuerzester Schnittpunkt E2 mit Gerade durch AP1 von E1 +// // Abstand zwischen den beiden Ellipsen +// return (AP1 - AP2).Norm() - (AP1 - R1).Norm() - (AP2 - R2).Norm(); // negative Werte sind bei Überlappung möglich // } /*Effective distance between two ellipses @@ -256,25 +256,25 @@ double JEllipse::GetEB() const { // 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) - { + 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); + } + 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 { @@ -286,88 +286,88 @@ double JEllipse::EffectiveDistanceToLine(const Line& l) const { // thanks to Sean Curtis. see manuals/Ellipsen/ellipseLineSean.pdf // double JEllipse::MinimumDistanceToLine(const Line& l) const { -// Point AinE = l.GetPoint1().CoordTransToEllipse(_center, _cosPhi, _sinPhi); -// Point BinE = l.GetPoint2().CoordTransToEllipse(_center, _cosPhi, _sinPhi); - -// // Action Point der Ellipse -// Point APinE = Point(_Xp, 0); -// Line linE = Line(AinE, BinE); -// double xa = linE.GetPoint1().GetX(); -// double ya = linE.GetPoint1().GetY(); -// double xb = linE.GetPoint2().GetX(); -// double yb = linE.GetPoint2().GetY(); -// double a = GetEA(); -// double b = GetEB(); -// Line l_strich_inE; -// // Punkt auf line mit kürzestem Abstand zum Action Point der Ellipse -// Point PinE = linE.ShortestPoint(APinE); - - -// double mindist; // Rückgabewert - -// // kürzester Punkt ist Randpunkt -// if (PinE == AinE || PinE == BinE) { -// mindist = 0; -// } else { -// double Dx, Dy // D -// , NormD, NormT; -// double Nx, Ny; // N -// double P1x, P1y; // P1 -// double Rx, Ry; // R -// double Tx, Ty; // R -// double d, e; -// double dummy; -// Dx = xa - xb; -// Dy = ya - yb; - -// if(Dx*ya - Dy*xa < 0) -// { -// Dx = -Dx; -// Dy = -Dy; -// } - -// NormD = sqrt(Dx*Dx + Dy*Dy); -// Dx /= NormD; -// Dy /= NormD; -// //N. The normal of the line -// Nx = -Dy; -// Ny = Dx; - -// Tx = -Dy/b; -// Ty = Dx/a; -// NormT = sqrt(Tx*Tx + Ty*Ty); -// Tx /= NormT; -// Ty /= NormT; - -// P1x = a*Nx; -// P1y = b*Ny; //Eq. (2.3) - -// dummy = Nx*xa + Ny*ya; //second part of Eq. (2.1) - -// e = Nx*P1x + Ny*P1y - dummy; //Eq. (2.4) - -// //R -// Rx = a*Tx; -// Ry = b*Ty; // Eq. (2.13) - -// d = Nx*Rx + Ny*Ry - dummy; - - -// /* if (1) -// { -// printf("\n----------- dca2 --------------\n"); -// printf("Dx = %.2f, Dy=%.2f (det=%.2f)\n", Dx, Dy, Dx*ya - Dy*xa); -// printf("Nx = %.2f, Ny=%.2f\n", Nx, Ny); -// printf("P1x = %.2f, P1y=%.2f\n", P1x, P1y); -// printf("Rx = %.2f, Ry=%.2f\n", Rx, Ry); -// printf("dummy=%f\n",dummy); -// printf("theta=%.2f\n",theta*180/PI); -// printf("e=%f, d=%f\n",e, d); -// printf("-------------------------\n\n"); -// }*/ -// mindist = d - e; -// } -// return mindist; +// Point AinE = l.GetPoint1().CoordTransToEllipse(_center, _cosPhi, _sinPhi); +// Point BinE = l.GetPoint2().CoordTransToEllipse(_center, _cosPhi, _sinPhi); + +// // Action Point der Ellipse +// Point APinE = Point(_Xp, 0); +// Line linE = Line(AinE, BinE); +// double xa = linE.GetPoint1().GetX(); +// double ya = linE.GetPoint1().GetY(); +// double xb = linE.GetPoint2().GetX(); +// double yb = linE.GetPoint2().GetY(); +// double a = GetEA(); +// double b = GetEB(); +// Line l_strich_inE; +// // Punkt auf line mit kürzestem Abstand zum Action Point der Ellipse +// Point PinE = linE.ShortestPoint(APinE); + + +// double mindist; // Rückgabewert + +// // kürzester Punkt ist Randpunkt +// if (PinE == AinE || PinE == BinE) { +// mindist = 0; +// } else { +// double Dx, Dy // D +// , NormD, NormT; +// double Nx, Ny; // N +// double P1x, P1y; // P1 +// double Rx, Ry; // R +// double Tx, Ty; // R +// double d, e; +// double dummy; +// Dx = xa - xb; +// Dy = ya - yb; + +// if(Dx*ya - Dy*xa < 0) +// { +// Dx = -Dx; +// Dy = -Dy; +// } + +// NormD = sqrt(Dx*Dx + Dy*Dy); +// Dx /= NormD; +// Dy /= NormD; +// //N. The normal of the line +// Nx = -Dy; +// Ny = Dx; + +// Tx = -Dy/b; +// Ty = Dx/a; +// NormT = sqrt(Tx*Tx + Ty*Ty); +// Tx /= NormT; +// Ty /= NormT; + +// P1x = a*Nx; +// P1y = b*Ny; //Eq. (2.3) + +// dummy = Nx*xa + Ny*ya; //second part of Eq. (2.1) + +// e = Nx*P1x + Ny*P1y - dummy; //Eq. (2.4) + +// //R +// Rx = a*Tx; +// Ry = b*Ty; // Eq. (2.13) + +// d = Nx*Rx + Ny*Ry - dummy; + + +// /* if (1) +// { +// printf("\n----------- dca2 --------------\n"); +// printf("Dx = %.2f, Dy=%.2f (det=%.2f)\n", Dx, Dy, Dx*ya - Dy*xa); +// printf("Nx = %.2f, Ny=%.2f\n", Nx, Ny); +// printf("P1x = %.2f, P1y=%.2f\n", P1x, P1y); +// printf("Rx = %.2f, Ry=%.2f\n", Rx, Ry); +// printf("dummy=%f\n",dummy); +// printf("theta=%.2f\n",theta*180/PI); +// printf("e=%f, d=%f\n",e, d); +// printf("-------------------------\n\n"); +// }*/ +// mindist = d - e; +// } +// return mindist; // } @@ -383,7 +383,7 @@ double JEllipse::EffectiveDistanceToLine(const Line& l) const { / \ / \ / \ - P1 * \ + P1 * \ *P2 1. find the closest distance between C1 and C2: d @@ -402,104 +402,104 @@ double JEllipse::EffectiveDistanceToLine(const Line& l) const { --> yB = yA - (yA-yC)*AB/AC */ // double JEllipse::MinimumDistanceToEllipse(const JEllipse& E2) const { -// JEllipse tmpE2 = E2; // verschobene Ellipse E2, so dass Berührung mit E1 -// Point v; // Verschiebungsvektor -// Point tmpC2 = Point(); // verschobenes Centrum von E2 -// const Point& C1 = this->GetCenter(); -// const Point& C2 = E2.GetCenter(); - -// //double d = this->Distance2d(E2); //dist closest approach between centres -// double d = 0.0; //this->Distance2d(E2); //dist closest approach between centres -// double distance; //between c1 and c2 -// double mind; // Rueckgabewert -// if (d < 0 || d != d) { -// char tmp[CLENGTH]; -// sprintf(tmp, "ERROR: \tEllipse::MinimumDistanceToEllipse() d=%f\n", d); -// Log->Write(tmp); -// exit(0); -// } - -// if ((C1 - C2).NormSquare() < J_EPS*J_EPS) { -// char tmp[CLENGTH]; -// sprintf(tmp, "ERROR: \tEllipse::MinimumDistanceToEllipse() m=0\n" -// "xc1: %f xc2: %f yc1: %f yc2: %f\n", C1.GetX(), C2.GetX(), -// C1.GetY(), C2.GetY()); -// Log->Write(tmp); -// exit(EXIT_FAILURE); -// //return 0.0; -// } -// // Verschiebungsvektor bestimmen und normieren -// v = (C2 - C1).Normalized(); -// tmpC2 = C1 + v * d; -// tmpE2.SetCenter(tmpC2); -// mind = this->EffectiveDistanceToEllipse(tmpE2, &distance); -// if (mind < 0) { //Overlapping -// mind = 0.0; -// } -// return mind; +// JEllipse tmpE2 = E2; // verschobene Ellipse E2, so dass Berührung mit E1 +// Point v; // Verschiebungsvektor +// Point tmpC2 = Point(); // verschobenes Centrum von E2 +// const Point& C1 = this->GetCenter(); +// const Point& C2 = E2.GetCenter(); + +// //double d = this->Distance2d(E2); //dist closest approach between centres +// double d = 0.0; //this->Distance2d(E2); //dist closest approach between centres +// double distance; //between c1 and c2 +// double mind; // Rueckgabewert +// if (d < 0 || d != d) { +// char tmp[CLENGTH]; +// sprintf(tmp, "ERROR: \tEllipse::MinimumDistanceToEllipse() d=%f\n", d); +// Log->Write(tmp); +// exit(0); +// } + +// if ((C1 - C2).NormSquare() < J_EPS*J_EPS) { +// char tmp[CLENGTH]; +// sprintf(tmp, "ERROR: \tEllipse::MinimumDistanceToEllipse() m=0\n" +// "xc1: %f xc2: %f yc1: %f yc2: %f\n", C1.GetX(), C2.GetX(), +// C1.GetY(), C2.GetY()); +// Log->Write(tmp); +// exit(EXIT_FAILURE); +// //return 0.0; +// } +// // Verschiebungsvektor bestimmen und normieren +// v = (C2 - C1).Normalized(); +// tmpC2 = C1 + v * d; +// tmpE2.SetCenter(tmpC2); +// mind = this->EffectiveDistanceToEllipse(tmpE2, &distance); +// if (mind < 0) { //Overlapping +// mind = 0.0; +// } +// return mind; // } // 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 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; + //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 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; + //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; + 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); + //return (-J_EPS_DIST < impliciteEllipse) && (impliciteEllipse < J_EPS_DIST); } /*bool Ellipse::IntersectionWithLine(const Line& line) { - //int Mathematics::IntersectionWithLine(ELLIPSE * E, float xa, float xb, float ya, float yb){ - // float xc = E->xc, yc = E->yc; - // float phi = E->phi; - // float xanew, yanew; - // float xbnew, ybnew; - // float delta = -1; - // float c,d; - // float a2 = E->a*E->a; - // float b2 = E->b*E->b; - // int is = 0; - // - // coord_trans(xa, ya, xc, yc, phi, &xanew, &yanew); - // coord_trans(xb, yb, xc, yc, phi, &xbnew, &ybnew); - // - // - // if(xanew != xbnew){ - // c = (yanew - ybnew)/(xanew - xbnew); - // d = yanew - c * xanew; - // float d2=d*d; - // //delta = 4*c*c*d*d/b2/b2 - 4*( d*d/b2 - 1 )*( 1.0/a2 + c*c/b2 ); - // delta = 4*(1.0/a2 + c*c/b2 -d2/b2/a2); - // is = (delta < 0)?0:1; - // } - // else{ - // is = (E->a < fabs(xanew))?0:1; - // } - // return is; - exit(EXIT_FAILURE); // what are you looking for here? + //int Mathematics::IntersectionWithLine(ELLIPSE * E, float xa, float xb, float ya, float yb){ + // float xc = E->xc, yc = E->yc; + // float phi = E->phi; + // float xanew, yanew; + // float xbnew, ybnew; + // float delta = -1; + // float c,d; + // float a2 = E->a*E->a; + // float b2 = E->b*E->b; + // int is = 0; + // + // coord_trans(xa, ya, xc, yc, phi, &xanew, &yanew); + // coord_trans(xb, yb, xc, yc, phi, &xbnew, &ybnew); + // + // + // if(xanew != xbnew){ + // c = (yanew - ybnew)/(xanew - xbnew); + // d = yanew - c * xanew; + // float d2=d*d; + // //delta = 4*c*c*d*d/b2/b2 - 4*( d*d/b2 - 1 )*( 1.0/a2 + c*c/b2 ); + // delta = 4*(1.0/a2 + c*c/b2 -d2/b2/a2); + // is = (delta < 0)?0:1; + // } + // else{ + // is = (E->a < fabs(xanew))?0:1; + // } + // return is; + exit(EXIT_FAILURE); // what are you looking for here? } */ diff --git a/pedestrian/Ellipse.h b/pedestrian/Ellipse.h index 79ea2039b2dd17605a23e9b7a8cdcd1ed4ebe092..83947f7008dfbe59292b2086df9d0a8894a80d8a 100644 --- a/pedestrian/Ellipse.h +++ b/pedestrian/Ellipse.h @@ -27,84 +27,84 @@ */ #ifndef _ELLIPSE_H -#define _ELLIPSE_H +#define _ELLIPSE_H #include "../geometry/Line.h" #include "../general/Macros.h" #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); }; -#endif /* _ELLIPSE_H */ +#endif /* _ELLIPSE_H */ diff --git a/pedestrian/PedDistributor.cpp b/pedestrian/PedDistributor.cpp index 879839a9092ac51dc6b86fe4ae2b551f9215b685..6293f05b85e84d6f8ccdd70d064667911fcbe501 100644 --- a/pedestrian/PedDistributor.cpp +++ b/pedestrian/PedDistributor.cpp @@ -40,18 +40,18 @@ 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"; + _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() { @@ -59,82 +59,82 @@ StartDistributionRoom::~StartDistributionRoom() { int StartDistributionRoom::GetAgentsNumber() const { - return _nPeds; + return _nPeds; } // Setter-Funktionen void StartDistributionRoom::SetRoomID(int id) { - _roomID = id; + _roomID = id; } int StartDistributionRoom::GetAge() const { - return _age; + return _age; } void StartDistributionRoom::SetAge(int age) { - _age = age; + _age = age; } const std::string& StartDistributionRoom::GetGender() const { - return _gender; + return _gender; } void StartDistributionRoom::SetGender(const std::string& gender) { - _gender = gender; + _gender = gender; } int StartDistributionRoom::GetGoalId() const { - return _goalID; + return _goalID; } void StartDistributionRoom::SetGoalId(int goalId) { - _goalID = goalId; + _goalID = goalId; } int StartDistributionRoom::GetGroupId() const { - return _groupID; + return _groupID; } void StartDistributionRoom::SetGroupId(int groupId) { - _groupID = groupId; + _groupID = groupId; } int StartDistributionRoom::GetHeight() const { - return _height; + return _height; } void StartDistributionRoom::SetHeight(int height) { - _height = height; + _height = height; } int StartDistributionRoom::GetRoomId() const { - return _roomID; + return _roomID; } void StartDistributionRoom::SetRoomId(int roomId) { - _roomID = roomId; + _roomID = roomId; } int StartDistributionRoom::GetRouteId() const { - return _routeID; + return _routeID; } void StartDistributionRoom::SetRouteId(int routeId) { - _routeID = routeId; + _routeID = routeId; } int StartDistributionRoom::GetRouterId() const { - return _routerID; + return _routerID; } void StartDistributionRoom::SetRouterId(int routerId) { - _routerID = routerId; + _routerID = routerId; } void StartDistributionRoom::SetAgentsNumber(int N) { - _nPeds = N; + _nPeds = N; } @@ -142,7 +142,7 @@ void StartDistributionRoom::SetAgentsNumber(int N) { StartDistributionSubRoom ************************************************************/ StartDistributionSubroom::StartDistributionSubroom() : StartDistributionRoom() { - _subroomID = -1; + _subroomID = -1; } @@ -150,13 +150,13 @@ StartDistributionSubroom::~StartDistributionSubroom() { } int StartDistributionSubroom::GetSubroomID() const { - return _subroomID; + return _subroomID; } // Setter-Funktionen void StartDistributionSubroom::SetSubroomID(int i) { - _subroomID = i; + _subroomID = i; } @@ -165,473 +165,473 @@ void StartDistributionSubroom::SetSubroomID(int i) { ************************************************************/ 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); + _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; + 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(); + 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; + return _v0; } Distribution* PedDistributor::GetBmax() const { - return _Bmax; + return _Bmax; } Distribution* PedDistributor::GetBmin() const { - return _Bmin; + return _Bmin; } Distribution* PedDistributor::GetAtau() const { - return _Atau; + return _Atau; } Distribution* PedDistributor::GetAmin() const { - return _Amin; + return _Amin; } Distribution* PedDistributor::GetTau() const { - return _Tau; + 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")) { - - 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")); - - } + _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")) { + + 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; + 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; + 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; + 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 +649,95 @@ 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)++; - } + 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; + 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; + 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); + return Point(_startX, _startY); } double StartDistributionRoom::GetPatience() const { - return _patience; + return _patience; } void StartDistributionRoom::SetPatience(double patience) { - _patience = patience; + _patience = patience; } diff --git a/pedestrian/PedDistributor.h b/pedestrian/PedDistributor.h index bfd34df8aff1c946929d5b57c5f97a3c32cb99e9..8b795024fd16af027ea54220de7396cbc1377312 100644 --- a/pedestrian/PedDistributor.h +++ b/pedestrian/PedDistributor.h @@ -26,7 +26,7 @@ */ #ifndef _PEDDISTRIBUTOR_H -#define _PEDDISTRIBUTOR_H +#define _PEDDISTRIBUTOR_H #include <vector> #include <string> @@ -39,115 +39,115 @@ /************************************************************ 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 */ +#endif /* _PEDDISTRIBUTOR_H */ diff --git a/pedestrian/Pedestrian.cpp b/pedestrian/Pedestrian.cpp index 615e7d56664a66e2732e3fbfd9a974869f2da14d..284c397ff0a1624e5731fb142feb798fa68cf22e 100644 --- a/pedestrian/Pedestrian.cpp +++ b/pedestrian/Pedestrian.cpp @@ -41,370 +41,370 @@ 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; + _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; + if(_navLine) delete _navLine; } void Pedestrian::SetID(int i) { - _id = i; + _id = i; } void Pedestrian::SetRoomID(int i, string roomCaption) { - _roomID = i; - _roomCaption=roomCaption; + _roomID = i; + _roomCaption=roomCaption; } void Pedestrian::SetSubRoomID(int i) { - _subRoomID = i; + _subRoomID = i; } void Pedestrian::SetMass(double m) { - _mass = m; + _mass = m; } void Pedestrian::SetTau(double tau) { - _tau = tau; + _tau = tau; } void Pedestrian::SetEllipse(const JEllipse& e) { - _ellipse = e; + _ellipse = e; } void Pedestrian::SetExitIndex(int i) { - _exitIndex = i; - //save that destination for that room - _mentalMap[GetUniqueRoomID()] = i; - _destHistory.push_back(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()); + //_navLine = l; + _navLine->SetPoint1(l->GetPoint1()); + _navLine->SetPoint2(l->GetPoint2()); } void Pedestrian::SetPos(const Point& pos) { - _ellipse.SetCenter(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; + _lastCellPosition=cp; } void Pedestrian::SetV(const Point& v) { - _ellipse.SetV(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); + _ellipse.SetV0(v0); } void Pedestrian::Setdt(double dt) { - _deltaT = dt; + _deltaT = dt; } double Pedestrian::Getdt() { - return _deltaT; + return _deltaT; } void Pedestrian::SetTrip(const vector<int>& trip){ - _trip=trip; + _trip=trip; } int Pedestrian::GetID() const { - return _id; + return _id; } int Pedestrian::GetRoomID() const { - return _roomID; + return _roomID; } int Pedestrian::GetSubRoomID() const { - return _subRoomID; + return _subRoomID; } double Pedestrian::GetMass() const { - return _mass; + return _mass; } double Pedestrian::GetTau() const { - return _tau; + return _tau; } const JEllipse& Pedestrian::GetEllipse() const { - return _ellipse; + return _ellipse; } int Pedestrian::GetExitIndex() const { - return _exitIndex; + return _exitIndex; } NavLine* Pedestrian::GetExitLine() const { - return _navLine; + return _navLine; } const vector<int>& Pedestrian::GetTrip() const{ - return _trip; + return _trip; } // return the unique subroom Identifier int Pedestrian::GetUniqueRoomID() const { - return _roomID * 1000 + _subRoomID; + 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()]; - } + if (_mentalMap.count(GetUniqueRoomID()) == 0) { + return -1; + } else { + return _mentalMap[GetUniqueRoomID()]; + } } int Pedestrian::GetLastDestination() { - if(_destHistory.size() == 0) - return -1; - else - return _destHistory.back(); + 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; + if(_oldRoomID != GetRoomID() || _oldSubRoomID != GetSubRoomID()) { + _oldRoomID = GetRoomID(); + _oldSubRoomID = GetSubRoomID(); + return true; + } + return false; } int Pedestrian::GetDestinationCount() { - return _destHistory.size(); + return _destHistory.size(); } // erase the peds memory void Pedestrian::ClearMentalMap(){ - _mentalMap.clear(); - _exitIndex=-1; + _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; + 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(); + return _ellipse.GetCenter(); } int Pedestrian::GetCellPos() const { - return _lastCellPosition; + return _lastCellPosition; } const Point& Pedestrian::GetV() const { - return _ellipse.GetV(); + return _ellipse.GetV(); } const Point& Pedestrian::GetV0() const { - return _V0; + return _V0; } double Pedestrian::GetV0Norm() const { - return _ellipse.GetV0()*_building->GetRoom(_roomID)->GetSubRoom(_subRoomID)->GetCosAngleWithHorizontal(); + return _ellipse.GetV0()*_building->GetRoom(_roomID)->GetSubRoom(_subRoomID)->GetCosAngleWithHorizontal(); } //get axis in the walking direction double Pedestrian::GetLargerAxis() const { - return _ellipse.GetEA(); + return _ellipse.GetEA(); } //get axis in the shoulder direction = orthogonal to the walking direction double Pedestrian::GetSmallerAxis() const { - return _ellipse.GetEB(); + 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); + 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; + const Point& pos = GetPos(); + Point delta = target - pos; + Point new_v0; - new_v0 = delta.Normalized(); + 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; + // 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; + return _timeInJam; } // set the new orientation flag @@ -412,267 +412,267 @@ double Pedestrian::GetTimeInJam() const { // 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; - } + //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); + //return true; + return (_patienceTime<_timeInJam); } void Pedestrian::ResetTimeInJam(){ - _timeInJam=0.0; + _timeInJam=0.0; } void Pedestrian::UpdateTimeInJam(){ - _timeInJam+=_deltaT; + _timeInJam+=_deltaT; } //TODO: magic void Pedestrian::UpdateJamData(){ - if(GetV().NormSquare()<0.25*GetV0().NormSquare()){ - _timeInJam+=_deltaT; - }else{ - _timeInJam/=2.0; - } + if(GetV().NormSquare()<0.25*GetV0().NormSquare()){ + _timeInJam+=_deltaT; + }else{ + _timeInJam/=2.0; + } } void Pedestrian::UpdateReroutingTime(){ - _timeBeforeRerouting-=_deltaT; + _timeBeforeRerouting-=_deltaT; } void Pedestrian::RerouteIn(double time){ - _reroutingEnabled=true; - _timeBeforeRerouting=time; + _reroutingEnabled=true; + _timeBeforeRerouting=time; } bool Pedestrian::IsReadyForRerouting(){ - return(_reroutingEnabled &&(_timeBeforeRerouting<=0.0)); + return(_reroutingEnabled &&(_timeBeforeRerouting<=0.0)); } double Pedestrian::GetAge() const { - return _age; + return _age; } void Pedestrian::SetAge(double age) { - _age = age; + _age = age; } string Pedestrian::GetGender() const { - return _gender; + return _gender; } void Pedestrian::SetGender(string gender) { - _gender = gender; + _gender = gender; } double Pedestrian::GetHeight() const { - return _height; + return _height; } int Pedestrian::GetGroup() const { - return _group; + return _group; } void Pedestrian::SetGroup(int group) { - _group = group; + _group = group; } void Pedestrian::SetHeight(double height) { - _height = height; + _height = height; } void Pedestrian::ResetRerouting(){ - _reroutingEnabled=false; - _timeBeforeRerouting=-1.00; + _reroutingEnabled=false; + _timeBeforeRerouting=-1.00; } void Pedestrian::SetRecordingTime(double timeInSec){ - _recordingTime=timeInSec; + _recordingTime=timeInSec; } double Pedestrian::GetRecordingTime() const{ - return _recordingTime; + 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 ); + //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())); + return (_navLine->DistTo(GetPos())); } void Pedestrian::SetFinalDestination(int final) { - _desiredFinalDestination = final; + _desiredFinalDestination = final; } int Pedestrian::GetFinalDestination() const { - return _desiredFinalDestination; + return _desiredFinalDestination; } ///@deprecated void Pedestrian::WritePath(ofstream& file, Building* building){ - map<int, int>::iterator iter; + 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; - } - } + 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; + map<int, int>::iterator iter; + string path; - 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; + 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::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); + 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(); + _lastPosition=GetPos(); } double Pedestrian::GetDistanceSinceLastRecord(){ - return (_lastPosition-GetPos()).Norm(); + return (_lastPosition-GetPos()).Norm(); } double Pedestrian::GetGlobalTime(){ - return _globalTime; + return _globalTime; } void Pedestrian::SetRouter(Router* router) { - _router=router; + _router=router; } Router* Pedestrian::GetRouter() const { - return _router; + 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); + 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()); + return _building->GetRoom(_roomID)->GetSubRoom(_subRoomID)->GetElevation(GetPos()); } void Pedestrian::SetGlobalTime(double time){ - _globalTime=time; + _globalTime=time; } double Pedestrian::GetPatienceTime() const { - return _patienceTime; + return _patienceTime; } void Pedestrian::SetPatienceTime(double patienceTime) { - _patienceTime = patienceTime; + _patienceTime = patienceTime; } const Building* Pedestrian::GetBuilding() { - return _building; + return _building; } void Pedestrian::SetBuilding(Building* building) { - _building = building; + _building = building; } void Pedestrian::SetSpotlight(bool spotlight){ - _spotlight=spotlight; + _spotlight=spotlight; } bool Pedestrian::GetSpotlight(){ - return !_enableSpotlight || _spotlight; + return !_enableSpotlight || _spotlight; } void Pedestrian::ActivateSpotlightSystem(bool status){ - _enableSpotlight=status; + _enableSpotlight=status; } diff --git a/pedestrian/Pedestrian.h b/pedestrian/Pedestrian.h index 956e4c0e0b58d0ca6aa7a01ecfdace6b4c7a2790..e580a279da9d87d1ec24ca6356874841b460e91a 100644 --- a/pedestrian/Pedestrian.h +++ b/pedestrian/Pedestrian.h @@ -26,7 +26,7 @@ */ #ifndef _PEDESTRIAN_H -#define _PEDESTRIAN_H +#define _PEDESTRIAN_H #include <vector> #include <queue> @@ -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 */ +#endif /* _PEDESTRIAN_H */ diff --git a/poly2tri/common/shapes.h b/poly2tri/common/shapes.h index 8c19d91ef8e902cfc00afaa37af7775ffa4d2e03..d3761def2ecd4f0e4b3b8d7c4569f65d73d0b950 100644 --- a/poly2tri/common/shapes.h +++ b/poly2tri/common/shapes.h @@ -40,283 +40,283 @@ namespace p2t { -struct Edge; + struct Edge; -struct Point { + struct Point { - double x, y; + double x, y; - /// Default constructor does nothing (for performance). - Point() - { - x = 0.0; - y = 0.0; - } + /// 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; + /// The edges this point constitutes an upper ending point + std::vector<Edge*> edge_list; - /// Construct using coordinates. + /// 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 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_; - } + /// 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; - } + /// 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; - } + /// 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; - } + /// 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; - } + /// 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); - } + /// 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; - } + /// 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 { + // Represents a simple polygon's edge + struct Edge { - Point* p, *q; + Point* p, *q; - /// Constructor + /// 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) { + { + if (p1.y > p2.y) { q = &p1; p = &p2; - } else if (p1.x == p2.x) { - // Repeat points - assert(false); + } 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) { + 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; } - 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); -} + /// 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); -} + /// 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); -} + /// 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; + } -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; -} + /// 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 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 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); -} + /// 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 Point* Triangle::GetPoint(const int& index) + { + return points_[index]; + } -inline Triangle* Triangle::GetNeighbor(const int& index) -{ - return neighbors_[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(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(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::Contains(Point* p, Point* q) + { + return Contains(p) && Contains(q); + } -inline bool Triangle::IsInterior() -{ - return interior_; -} + inline bool Triangle::IsInterior() + { + return interior_; + } -inline void Triangle::IsInterior(bool b) -{ - interior_ = b; -} + inline void Triangle::IsInterior(bool b) + { + interior_ = b; + } } diff --git a/poly2tri/common/utils.h b/poly2tri/common/utils.h index dfe2a77d258359b21d04b09d1dc58dbb849451b8..cccfabf03c054f73e5b8ed692210a614508bc59a 100644 --- a/poly2tri/common/utils.h +++ b/poly2tri/common/utils.h @@ -34,88 +34,88 @@ // Otherwise #defines like M_PI are undeclared under Visual Studio #define _USE_MATH_DEFINES -#define M_PI 3.14159265358979323846 +#define M_PI 3.14159265358979323846 #include <exception> #include <math.h> 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) -{ - 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; + 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; } - return CW; -} -/* -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) { + /* + 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) { + 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; + 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; } - return true; -} } diff --git a/poly2tri/sweep/advancing_front.h b/poly2tri/sweep/advancing_front.h index bab73d449ca0a079c3004e32d5f0955c7cfee1fb..4f751854cad881bf959375a83a321e023937f69a 100644 --- a/poly2tri/sweep/advancing_front.h +++ b/poly2tri/sweep/advancing_front.h @@ -36,82 +36,82 @@ namespace p2t { -struct Node; + struct Node; -// Advancing front node -struct Node { - Point* point; - Triangle* triangle; + // Advancing front node + struct Node { + Point* point; + Triangle* triangle; - Node* next; - Node* prev; + Node* next; + Node* prev; - double value; + 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: + // Advancing front + class AdvancingFront { + public: -AdvancingFront(Node& head, Node& tail); -// Destructor -~AdvancingFront(); + 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); + 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); + /// Locate insertion point along advancing front + Node* LocateNode(const double& x); -Node* LocatePoint(const Point* point); + Node* LocatePoint(const Point* point); -private: + private: -Node* head_, *tail_, *search_node_; + Node* head_, *tail_, *search_node_; -Node* FindSearchNode(const double& x); -}; + Node* FindSearchNode(const double& x); + }; -inline Node* AdvancingFront::head() -{ - return head_; -} -inline void AdvancingFront::set_head(Node* node) -{ - head_ = node; -} + 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::tail() + { + return tail_; + } + inline void AdvancingFront::set_tail(Node* node) + { + tail_ = node; + } -inline Node* AdvancingFront::search() -{ - return search_node_; -} + inline Node* AdvancingFront::search() + { + return search_node_; + } -inline void AdvancingFront::set_search(Node* node) -{ - search_node_ = node; -} + inline void AdvancingFront::set_search(Node* node) + { + search_node_ = node; + } } diff --git a/poly2tri/sweep/cdt.h b/poly2tri/sweep/cdt.h index baf6ca7dddbd7b4f5b12ae3c81820da26b8de34d..4b835acdc2c3b9b59b3ef5abc1ea5f74dc9201c6 100644 --- a/poly2tri/sweep/cdt.h +++ b/poly2tri/sweep/cdt.h @@ -44,61 +44,61 @@ namespace p2t { -class CDT -{ -public: + class CDT + { + public: - /** - * Constructor - add polyline with non repeating points - * - * @param polyline - */ - CDT(std::vector<Point*> polyline); + /** + * Constructor - add polyline with non repeating points + * + * @param polyline + */ + CDT(std::vector<Point*> polyline); - /** - * Destructor - clean up memory - */ - ~CDT(); + /** + * Destructor - clean up memory + */ + ~CDT(); - /** - * Add a hole - * - * @param polyline - */ - void AddHole(std::vector<Point*> polyline); + /** + * Add a hole + * + * @param polyline + */ + void AddHole(std::vector<Point*> polyline); - /** - * Add a steiner point - * - * @param point - */ - void AddPoint(Point* point); + /** + * 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(); + /** + * Triangulate - do this AFTER you've added the polyline, holes, and Steiner points + */ + void Triangulate(); - /** - * Get CDT triangles - */ - std::vector<Triangle*> GetTriangles(); + /** + * Get CDT triangles + */ + std::vector<Triangle*> GetTriangles(); - /** - * Get triangle map - */ - std::list<Triangle*> GetMap(); + /** + * Get triangle map + */ + std::list<Triangle*> GetMap(); private: - /** - * Internals - */ + /** + * Internals + */ - SweepContext* sweep_context_; - Sweep* sweep_; + SweepContext* sweep_context_; + Sweep* sweep_; -}; + }; } diff --git a/poly2tri/sweep/sweep.cpp b/poly2tri/sweep/sweep.cpp index ad001e74fa13c5814527439fe013516a6ed5e1d7..854dfd4b6548328b35f6db9a040a2accbfcc463f 100644 --- a/poly2tri/sweep/sweep.cpp +++ b/poly2tri/sweep/sweep.cpp @@ -39,772 +39,772 @@ 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; + 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; + // 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; + 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; + 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; + 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 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; + /* 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& 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); - } + 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]; - } + // 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 f62c4cc3f2968f7587e017c1f6624ebe0c6c9579..eb74e00c2b9103f256d1c895dd01441126ae6c99 100644 --- a/poly2tri/sweep/sweep.h +++ b/poly2tri/sweep/sweep.h @@ -43,210 +43,210 @@ namespace p2t { -class SweepContext; -struct Node; -struct Point; -struct Edge; -class Triangle; - -class Sweep -{ -public: - - /** - * Triangulate - * - * @param tcx - */ - void Triangulate(SweepContext& tcx); + 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); - - /** + /** + * 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); + 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); - - /** + // 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. @@ -257,9 +257,9 @@ private: * @param op * @return */ - Point& NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op); + 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 @@ -272,13 +272,13 @@ private: * @param t * @param p */ - void FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, Triangle& t, Point& p); + void FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, Triangle& t, Point& p); - void FinalizationPolygon(SweepContext& tcx); + void FinalizationPolygon(SweepContext& tcx); - std::vector<Node*> nodes_; + std::vector<Node*> nodes_; -}; + }; } diff --git a/poly2tri/sweep/sweep_context.cpp b/poly2tri/sweep/sweep_context.cpp index 6c0b0447dd0e6dbac2c7b38f8190a212dc79a0fd..e780e1c177051d76be4ca853776581f3aba3dd8d 100644 --- a/poly2tri/sweep/sweep_context.cpp +++ b/poly2tri/sweep/sweep_context.cpp @@ -174,8 +174,8 @@ void SweepContext::MeshClean(Triangle& triangle) triangles.push_back(&triangle); while(!triangles.empty()){ - Triangle *t = triangles.back(); - triangles.pop_back(); + Triangle *t = triangles.back(); + triangles.pop_back(); if (t != NULL && !t->IsInterior()) { t->IsInterior(true); diff --git a/poly2tri/sweep/sweep_context.h b/poly2tri/sweep/sweep_context.h index 266408dc2e089afb40c76dde3142fe68bbb15781..83c2b4c25b20df9a5caa95cfe83c43647eb4a621 100644 --- a/poly2tri/sweep/sweep_context.h +++ b/poly2tri/sweep/sweep_context.h @@ -28,159 +28,159 @@ * 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 87422640186ae58239ac5fb6858867bd532db832..b385a83c37e495a8f753d27275caa2ae05b509be 100644 --- a/routing/AccessPoint.cpp +++ b/routing/AccessPoint.cpp @@ -33,269 +33,269 @@ 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; + _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; + //if(_navLine) delete _navLine; } int AccessPoint::GetID() { - return _id; + return _id; } int AccessPoint::IsClosed(){ - return _isClosed; + return _isClosed; } void AccessPoint::SetClosed(int isClosed){ - _isClosed=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; + return pCentre; } void AccessPoint::SetFinalGoalOutside(bool isFinal) { - _finalGoalOutside=isFinal; + _finalGoalOutside=isFinal; } bool AccessPoint::GetFinalGoalOutside(){ - return _finalGoalOutside; + return _finalGoalOutside; } //TODO: possibly remove void AccessPoint::AddIntermediateDest(int final, int inter){ - _mapDestToAp[final]=inter; + _mapDestToAp[final]=inter; } void AccessPoint::AddFinalDestination(int UID, double distance){ - _mapDestToDist[UID]=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]; + //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(); + 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); + //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]; + //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(); - } + 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; + _room1ID=r1; + _room2ID=r2; } 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; + if((roomID!=_room1ID) && (roomID!=_room2ID)){ + return false; + } + return true; } 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){ -// vector<Pedestrian*>::iterator it; -// it = find (_transitPedestrians.begin(), _transitPedestrians.end(), ped); -// if(it==_transitPedestrians.end()){ -// cout<<" Ped not found"<<endl; -// }else{ -// _transitPedestrians.erase(it); -// } +// vector<Pedestrian*>::iterator it; +// it = find (_transitPedestrians.begin(), _transitPedestrians.end(), ped); +// if(it==_transitPedestrians.end()){ +// cout<<" Ped not found"<<endl; +// }else{ +// _transitPedestrians.erase(it); +// } //} //void AccessPoint::AddTransitPed(Pedestrian* ped){ -// _transitPedestrians.push_back(ped); +// _transitPedestrians.push_back(ped); //} void AccessPoint::SetNavLine(NavLine* line) { - _navLine=line; + _navLine=line; } NavLine* AccessPoint::GetNavLine() const { - return _navLine; + return _navLine; } //const vector<Pedestrian*>& AccessPoint::GetAllTransitPed() const{ -// return _transitPedestrians; +// return _transitPedestrians; //} const vector <AccessPoint*>& AccessPoint::GetConnectingAPs(){ - return _connectingAPs; + 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); - } + 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]; + return _navigationGraphTo[UID]; } void AccessPoint::AddTransitAPsTo(int UID,AccessPoint* ap){ - _navigationGraphTo[UID].push_back(ap); + _navigationGraphTo[UID].push_back(ap); } void AccessPoint::Reset(int UID){ - _navigationGraphTo[UID].clear(); + _navigationGraphTo[UID].clear(); } void AccessPoint::SetFriendlyName(const std::string& name){ - _friendlyName=name; + _friendlyName=name; } const std::string AccessPoint::GetFriendlyName(){ - return _friendlyName; + 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; - - //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 413e6e90f5739ec7db1d6c9c939712ee668e62b4..5bb6f233823560d27c5c092e71a72bc7a1d247aa 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,196 @@ #include "../pedestrian/Pedestrian.h" #include "../geometry/Point.h" #include "../geometry/Line.h" - -class AccessPoint { -public: - - /** - * create a new access point with the provided data - * - * @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; - -}; - + + class AccessPoint { + public: + + /** + * create a new access point with the provided data + * + * @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; + + }; + #endif /* ACCESSPOINT_H_ */ diff --git a/routing/CognitiveMapRouter.h b/routing/CognitiveMapRouter.h index b4cb293560844c1d31af10de344ce30fd0b29028..ef372d280fb7b9d062cf8e2c101cdfdf1695ae77 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 26281c1a2e518f2d2171da71f06b507c9852fe47..a16d0bcb491d4c68a7a8ad42abbeaaa84330eeee 100644 --- a/routing/ConvexDecomp.h +++ b/routing/ConvexDecomp.h @@ -56,17 +56,17 @@ struct FaceInfo2 -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef CGAL::Partition_traits_2<K> Traits; -typedef CGAL::Is_convex_2<Traits> Is_convex_2; -typedef Traits::Polygon_2 Polygon_2; -//typedef CGAL::Polygon_2<K> Polygon_2; -typedef Traits::Point_2 Point_2; -typedef Polygon_2::Vertex_const_iterator Vertex_iterator; -typedef std::list<Polygon_2> Polygon_list; -typedef Polygon_list::const_iterator Polygon_iterator; -typedef CGAL::Partition_is_valid_traits_2<Traits, Is_convex_2> Validity_traits; -typedef Polygon_2::Edge_const_iterator Edge_iterator; +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Partition_traits_2<K> Traits; +typedef CGAL::Is_convex_2<Traits> Is_convex_2; +typedef Traits::Polygon_2 Polygon_2; +//typedef CGAL::Polygon_2<K> Polygon_2; +typedef Traits::Point_2 Point_2; +typedef Polygon_2::Vertex_const_iterator Vertex_iterator; +typedef std::list<Polygon_2> Polygon_list; +typedef Polygon_list::const_iterator Polygon_iterator; +typedef CGAL::Partition_is_valid_traits_2<Traits, Is_convex_2> Validity_traits; +typedef Polygon_2::Edge_const_iterator Edge_iterator; typedef CGAL::Triangulation_vertex_base_2<K> Vb; @@ -78,15 +78,15 @@ typedef CGAL::Constrained_Delaunay_triangulation_2<K, TDS, Itag> CDT; -typedef CGAL::Alpha_shape_vertex_base_2<K> Av; -typedef CGAL::Triangulation_face_base_2<K> Tf; -typedef CGAL::Alpha_shape_face_base_2<K,Tf> Af; -typedef CGAL::Triangulation_default_data_structure_2<K,Av,Af> Tds; -typedef CGAL::Delaunay_triangulation_2<K,Tds> DT; +typedef CGAL::Alpha_shape_vertex_base_2<K> Av; +typedef CGAL::Triangulation_face_base_2<K> Tf; +typedef CGAL::Alpha_shape_face_base_2<K,Tf> Af; +typedef CGAL::Triangulation_default_data_structure_2<K,Av,Af> Tds; +typedef CGAL::Delaunay_triangulation_2<K,Tds> DT; -typedef CGAL::Polygon_with_holes_2<K> Polygon_with_holes_2; +typedef CGAL::Polygon_with_holes_2<K> Polygon_with_holes_2; -typedef CGAL::Segment_2<K> Segment_2; +typedef CGAL::Segment_2<K> Segment_2; //fast delauney //typedef CGAL::Alpha_shape_vertex_base_3<K> Vb; @@ -100,7 +100,7 @@ typedef CGAL::Segment_2<K> Segment_2; typedef CGAL::Alpha_shape_2<DT> Alpha_shape_2; typedef Alpha_shape_2::Alpha_iterator Alpha_iterator; -typedef Alpha_shape_2::Vertex_iterator Alpha_vertex_iterator; +typedef Alpha_shape_2::Vertex_iterator Alpha_vertex_iterator; @@ -168,66 +168,66 @@ void insert_polygon(CDT& cdt,const Polygon_2& polygon){ 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; - } + { + 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 @@ -252,13 +252,13 @@ int test_alpha_shape() getc(stdin); for (std::list<Point_2>::const_iterator iterator = env.begin(), end = env.end(); iterator != end; ++iterator) { - std::cout << *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); @@ -270,7 +270,7 @@ int test_alpha_shape() } 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; @@ -281,7 +281,7 @@ void print_polygon (const CGAL::Polygon_2<Kernel, Container>& P) } 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 = "; diff --git a/routing/DTriangulation.cpp b/routing/DTriangulation.cpp index b628e433e9081e4d5bf6754762a598ed8eabef9c..35478e941654167c000bc4151aefd83f33b3bd7f 100644 --- a/routing/DTriangulation.cpp +++ b/routing/DTriangulation.cpp @@ -10,43 +10,43 @@ using namespace std; DTriangulation::DTriangulation() { - _cdt=NULL; + _cdt=NULL; } 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() { - _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) { - 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) { - 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 3f81cd87510562407559a429c098a6464b2f1b6e..b1c0ef83547577f8140904db553d8bc9d660c0a8 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 be3b86402966e488b770faa249c1b3fb53236856..a8a9c63d9c58b806e8b253e4c508537ba02255e1 100644 --- a/routing/DirectionStrategy.cpp +++ b/routing/DirectionStrategy.cpp @@ -74,22 +74,22 @@ Point DirectionMinSeperationShorterLine::GetTarget(Room* room, Pedestrian* ped) 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 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; - } + if ( e_neu.IsInLineSegment(Lot) ) + { + return Lot; + } + else + { + return ExitMiddle; + } } diff --git a/routing/DirectionStrategy.h b/routing/DirectionStrategy.h index 82bfbba3aab052c934d32e45b02332102dd8ce17..122abad11e0f3219e7e97e304ac762c3398bb796 100644 --- a/routing/DirectionStrategy.h +++ b/routing/DirectionStrategy.h @@ -25,7 +25,7 @@ */ #ifndef _DIRECTIONSTRATEGY_H -#define _DIRECTIONSTRATEGY_H +#define _DIRECTIONSTRATEGY_H class Room; @@ -34,43 +34,43 @@ 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; + public: + virtual Point GetTarget(Room* room, Pedestrian* ped) const; }; class DirectionMinSeperation : public DirectionStrategy { - public: - virtual Point GetTarget(Room* room, Pedestrian* ped) const; + public: + virtual Point GetTarget(Room* room, Pedestrian* ped) const; }; class DirectionMinSeperationShorterLine : public DirectionStrategy { - public: - virtual Point GetTarget(Room* room, Pedestrian* ped) const; + public: + virtual Point GetTarget(Room* room, Pedestrian* ped) const; }; class DirectionInRangeBottleneck : public DirectionStrategy { - public: - virtual Point GetTarget(Room* room, Pedestrian* ped) const; + public: + virtual Point GetTarget(Room* room, Pedestrian* ped) const; }; class DirectionGeneral : public DirectionStrategy { - public: - virtual Point GetTarget(Room* room, Pedestrian* ped) const; + public: + virtual Point GetTarget(Room* room, Pedestrian* ped) const; }; -#endif /* _DIRECTIONSTRATEGY_H */ +#endif /* _DIRECTIONSTRATEGY_H */ diff --git a/routing/DummyRouter.cpp b/routing/DummyRouter.cpp index 1105d23e32898acba25650181c05b307c359bba1..18ff7c1f3efa80955f8567837bfd9277e6a41ae8 100644 --- a/routing/DummyRouter.cpp +++ b/routing/DummyRouter.cpp @@ -10,7 +10,7 @@ #include "../pedestrian/Pedestrian.h" DummyRouter::DummyRouter() { - _building=NULL; + _building=NULL; } DummyRouter::~DummyRouter() { @@ -18,31 +18,31 @@ DummyRouter::~DummyRouter() { } int DummyRouter::FindExit(Pedestrian* p) { - p->SetExitIndex(1); - //p->SetExitLine(_building->getGetCrossing(0)); - return 1; + 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 !!"); - - //dump all navigation lines - -// cout<<"crossing:"<<endl; -// for (map<int, Crossing*>::const_iterator iter = pCrossings.begin(); -// iter != pCrossings.end(); ++iter) { -// iter->second->WriteToErrorLog(); -// } -// for (map<int, Transition*>::const_iterator iter = pTransitions.begin(); -// iter != pTransitions.end(); ++iter) { -// iter->second->WriteToErrorLog(); -// } -// for (map<int, Hline*>::const_iterator iter = pHlines.begin(); -// iter != pHlines.end(); ++iter) { -// iter->second->WriteToErrorLog(); -// } -// exit(EXIT_FAILURE); + _building=b; + Log->Write("ERROR: \tdo not use this <<Dummy>> router !!"); + + //dump all navigation lines + +// cout<<"crossing:"<<endl; +// for (map<int, Crossing*>::const_iterator iter = pCrossings.begin(); +// iter != pCrossings.end(); ++iter) { +// iter->second->WriteToErrorLog(); +// } +// for (map<int, Transition*>::const_iterator iter = pTransitions.begin(); +// iter != pTransitions.end(); ++iter) { +// iter->second->WriteToErrorLog(); +// } +// for (map<int, Hline*>::const_iterator iter = pHlines.begin(); +// iter != pHlines.end(); ++iter) { +// iter->second->WriteToErrorLog(); +// } +// exit(EXIT_FAILURE); } diff --git a/routing/DummyRouter.h b/routing/DummyRouter.h index 929eaeb5d33cfcf4ce3a38094340c589fc4dc36e..88b6aa266fc3cd46db0ff5cebc20db7caa199cb4 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 267e6dac77f397d63fc03e45cf1769faccaaf7f3..cb4042f53c66d323f68c3d38a43ea8abb888dd00 100644 --- a/routing/GlobalRouter.cpp +++ b/routing/GlobalRouter.cpp @@ -46,487 +46,487 @@ 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(); + 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() - - 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, - _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); + 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, + _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); } 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); + 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; + //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; } @@ -538,524 +538,524 @@ void GlobalRouter::GetPath(Pedestrian*ped, int goalID, std::vector<SubRoom*>& pa 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]; - } + 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(); - } - } + 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 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; - } + 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; + } } 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; - } + // 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 + //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* 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; + 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){ - if(filename=="") return; - - 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); - } - - 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); - } - - 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* 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 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); - - //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"); + if(filename=="") return; + + 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); + } + + 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); + } + + 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* 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 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); + + //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"); } diff --git a/routing/GlobalRouter.h b/routing/GlobalRouter.h index aa9cc84a959d7f2c5985f6ba758c27c11ea3ab45..c1144f834d3e56e624fe1d4476601dd57d745c0b 100644 --- a/routing/GlobalRouter.h +++ b/routing/GlobalRouter.h @@ -49,145 +49,145 @@ 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 7c561c5058aaacadfcc6100ebcfc85c7a791625f..d7f971bb6bfb5ec826210c4b14f3de8f33c1a67e 100644 --- a/routing/GraphRouter.cpp +++ b/routing/GraphRouter.cpp @@ -17,7 +17,7 @@ using namespace std; GraphRouter::GraphRouter() { - _building=NULL; + _building=NULL; } GraphRouter::~GraphRouter() @@ -29,99 +29,99 @@ 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 + 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; - } + 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) diff --git a/routing/GraphRouter.h b/routing/GraphRouter.h index 3b33853cab862c5cb96e38c420cd1614e37dbd8f..814d82c6ea56ee4ea1d9cb95c1054b3f8dc750b8 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 e3e280d8dbbd081f05730a8f18f659ffafc978a4..cac83e2b6e23bb42445eb44e1fc3b20f54584598 100644 --- a/routing/MeshRouter.cpp +++ b/routing/MeshRouter.cpp @@ -15,44 +15,44 @@ using namespace std; MeshRouter::MeshRouter() { - _building=NULL; - _meshdata=NULL; + _building=NULL; + _meshdata=NULL; } MeshRouter::~MeshRouter() { - delete _meshdata; + 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; - } + 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 @@ -65,20 +65,20 @@ void print_path(vector<MeshEdge*>edge_path){ */ 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; - } + 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 @@ -132,848 +132,848 @@ int CutCircleCircle(Point mp1, double r1, Point mp2, double r2, * 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; + // 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 + 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 + 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); - } + //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; - - 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; + // 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.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; + //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); - } - } + 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(); + _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 { - 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 2b38f8ab21a402b5fa8babfb3d4987c7ede83da3..76391ffcbe7d492f612c133b1a07cbbc66975598 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 7e009f24d2b846e0af50ca0fd8153d5d0338298f..e1c0082e88e3d125bbf8c1d1c29995b50baaf821 100644 --- a/routing/NavMesh.cpp +++ b/routing/NavMesh.cpp @@ -22,2833 +22,2833 @@ using namespace std; NavMesh::NavMesh(Building* b) { - _building=b; + _building=b; } 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() { - //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]; + 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; + 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; + 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++) { + 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()); - } + JNode* old_node = _nodes[n]; + if (old_node->IsClockwise()) { + reverse(old_node->pHull.begin(), old_node->pHull.end()); + } - if (old_node->IsConvex() == false) { + if (old_node->IsConvex() == false) { - Triangulate(old_node); - } - } - Log->Write("INFO:\t...Done!"); + Triangulate(old_node); + } + } + Log->Write("INFO:\t...Done!"); - /* - //will hold the newly created elements - std::vector<JVertex*> new_vertices; - std::vector<JEdge*> new_edges; - std::vector<JObstacle*> new_obsts; + /* + //will hold the newly created elements + std::vector<JVertex*> new_vertices; + std::vector<JEdge*> new_edges; + std::vector<JObstacle*> new_obsts; - std::vector<JNode*> nodes_to_be_deleted; + std::vector<JNode*> nodes_to_be_deleted; - for (unsigned int n = 0; n < pNodes.size(); n++) { + 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()); - } + JNode* old_node = pNodes[n]; + if (old_node->IsClockwise()) { + reverse(old_node->pHull.begin(), old_node->pHull.end()); + } - if (old_node->IsConvex() == false) { + if (old_node->IsConvex() == false) { #ifdef _CGAL - string group=old_node->pGroup; + string group=old_node->pGroup; #ifdef _DEBUG - cout<<"convexifing:" <<group<< " ID: "<<old_node->id <<endl; + cout<<"convexifing:" <<group<< " ID: "<<old_node->id <<endl; #endif -// const char* myGroups[] = {"030"}; -// vector<string> nodes_to_plot (myGroups, myGroups + sizeof(myGroups) / sizeof(char*) ); +// const char* myGroups[] = {"030"}; +// vector<string> nodes_to_plot (myGroups, myGroups + sizeof(myGroups) / sizeof(char*) ); // -// if (IsElementInVector(nodes_to_plot, group) == false) -// continue; +// if (IsElementInVector(nodes_to_plot, group) == false) +// continue; - //schedule this JNode for deletion - nodes_to_be_deleted.push_back(old_node); + //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; + Polygon_2 polygon; + Polygon_list partition_polys; + Traits partition_traits; + Validity_traits validity_traits; - //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)); + //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)); - } + } - //polygon - try { - if(polygon.is_clockwise_oriented()) polygon.reverse_orientation(); + //polygon + try { + if(polygon.is_clockwise_oriented()) polygon.reverse_orientation(); - //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); + //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); - //check the created partitions - assert(CGAL::partition_is_valid_2(polygon.vertices_begin(), - polygon.vertices_end(), partition_polys.begin(), - partition_polys.end(), validity_traits)); + //check the created partitions + assert(CGAL::partition_is_valid_2(polygon.vertices_begin(), + polygon.vertices_end(), partition_polys.begin(), + partition_polys.end(), validity_traits)); - } - catch(const exception & e) { + } + catch(const exception & e) { - 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; - } + 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) { + //make the changes to the nav mesh + for (Polygon_iterator pit = partition_polys.begin(); + pit != partition_polys.end(); ++pit) { - 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); + 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_2 c2 =CGAL::centroid(pit->vertices_begin(),pit->vertices_end(),CGAL::Dimension_tag<0>()); + Point_2 c2 =CGAL::centroid(pit->vertices_begin(),pit->vertices_end(),CGAL::Dimension_tag<0>()); - new_node->pCentroid= Point(c2.x(),c2.y()); + 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]; + 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())))); - } + 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()); - } + 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){ + 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()); + 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]; + 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; - } + //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; - } + 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; + } - // 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); + } + } + } #endif - } - } + } + } #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; + 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(); + 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]; + // 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(); + JNode* new_node = pNodes.back(); + pNodes.pop_back(); - assert (node_to_delete->id != new_node->id && "Trying to remove the last node !"); + assert (node_to_delete->id != new_node->id && "Trying to remove the last node !"); - //making the transformation + //making the transformation - for(unsigned int i=0;i<new_node->pObstacles.size();i++){ - pObst[new_node->pObstacles[i]]->pNode0=node_to_delete->id; - } + for(unsigned int i=0;i<new_node->pObstacles.size();i++){ + pObst[new_node->pObstacles[i]]->pNode0=node_to_delete->id; + } - 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->pPortals.size();i++){ + JEdge* e= pEdges[new_node->pPortals[i]]; -// if(e->pNode0==node_to_delete->id || e->pNode1==node_to_delete->id){ +// if(e->pNode0==node_to_delete->id || e->pNode1==node_to_delete->id){ // -// }else{ +// }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; +// 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; + cout<<"deleting node: "<<node_to_delete->id<<endl; #endif - delete node_to_delete; - } + 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; + 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 + //final cleaning - UpdateEdges(); - UpdateObstacles(); + UpdateEdges(); + UpdateObstacles(); - //exit(0); + //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(); + 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(); + 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(); + 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(); + 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(); + 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)) { + 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 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 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) { - 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) { - 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) { - 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"); + Log->Write("INFO:\tFinalizing the mesh with an Alpha Shape"); - // WriteToFileTraVisTo("arena_envelope.xml",envelope); - //collect all possible vertices that form that envelope + // WriteToFileTraVisTo("arena_envelope.xml",envelope); + //collect all possible vertices that form that envelope - vector<Line> envelope; + vector<Line> 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); - } + 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); - - //walls - const vector<Wall>& walls = s->GetAllWalls(); - - 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; - - 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 < 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)); - } - } - - - const vector<Transition*>& transitions = s->GetAllTransitions(); - for (unsigned t = 0; t < transitions.size(); t++) { - - //if(IsCircleVisibleFromLine(env_center,env_radius,*transitions[t])==false) continue; - - 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 < 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)); - } - } - } - } - - 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(); + 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); + + //walls + const vector<Wall>& walls = s->GetAllWalls(); + + 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; + + 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 < 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)); + } + } + + + const vector<Transition*>& transitions = s->GetAllTransitions(); + for (unsigned t = 0; t < transitions.size(); t++) { + + //if(IsCircleVisibleFromLine(env_center,env_radius,*transitions[t])==false) continue; + + 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 < 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)); + } + } + } + } + + 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(); + 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) { - //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); - } - - 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; - } - } + //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; + } + } - 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) { - 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(); + 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(); + 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"?> + /* + <?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; + //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); - } - } - } + 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() { - 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) { // -// double StairAngle=34.0; // degrees -// double theta = ( StairAngle * M_PI / 180.0 ); -// double StairAreaToIgnore=5.0; +// double StairAngle=34.0; // degrees +// double theta = ( StairAngle * M_PI / 180.0 ); +// double StairAreaToIgnore=5.0; // -// Room* room=pBuilding->GetRoom(sub->GetRoomID()); -// coefficents[0]=0; -// coefficents[1]=0; -// coefficents[2]=room->GetZPos(); //default elevation +// Room* room=pBuilding->GetRoom(sub->GetRoomID()); +// coefficents[0]=0; +// coefficents[1]=0; +// coefficents[2]=room->GetZPos(); //default elevation // -// Stair* stair=dynamic_cast<Stair*>(sub); -// if(stair==NULL) -// { +// Stair* stair=dynamic_cast<Stair*>(sub); +// if(stair==NULL) +// { //// -//// if ((sub->GetAllCrossings().size()) -//// + sub->GetAllTransitions().size() >2) -//// return; +//// if ((sub->GetAllCrossings().size()) +//// + sub->GetAllTransitions().size() >2) +//// return; // -// Point projection; -// bool connection=false; +// Point projection; +// bool connection=false; // -// //check if the subroom is connected with a stair -// for (int i = 0; i < pBuilding->GetAnzRooms(); i++) { -// Room* r = pBuilding->GetRoom(i); -// for (int k = 0; k < r->GetAnzSubRooms(); k++) { -// SubRoom* s = r->GetSubRoom(k); -// Stair* st=dynamic_cast<Stair*>(s); -// if ((st!=NULL) && (s->GetSubRoomID()!=sub->GetSubRoomID()) ){ -// if(st->GetAllCrossings().size()==2) continue; -// if(sub->IsDirectlyConnectedWith(s)){ -// //get the middle point of the crossing -// //check the crossings -// const vector<Crossing*>& crossings1 = sub->GetAllCrossings(); -// const vector<Crossing*>& crossings2 = s->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){ -// Line axe(st->GetUp(), st->GetDown()); -// // projection=axe.ShortestPoint(crossings1[c1]->GetCentre()); -// projection=crossings1[c1]->GetCentre(); -// connection=true; -// goto DONE; -// } -// } -// } -// } -// } +// //check if the subroom is connected with a stair +// for (int i = 0; i < pBuilding->GetAnzRooms(); i++) { +// Room* r = pBuilding->GetRoom(i); +// for (int k = 0; k < r->GetAnzSubRooms(); k++) { +// SubRoom* s = r->GetSubRoom(k); +// Stair* st=dynamic_cast<Stair*>(s); +// if ((st!=NULL) && (s->GetSubRoomID()!=sub->GetSubRoomID()) ){ +// if(st->GetAllCrossings().size()==2) continue; +// if(sub->IsDirectlyConnectedWith(s)){ +// //get the middle point of the crossing +// //check the crossings +// const vector<Crossing*>& crossings1 = sub->GetAllCrossings(); +// const vector<Crossing*>& crossings2 = s->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){ +// Line axe(st->GetUp(), st->GetDown()); +// // projection=axe.ShortestPoint(crossings1[c1]->GetCentre()); +// projection=crossings1[c1]->GetCentre(); +// connection=true; +// goto DONE; +// } +// } +// } +// } +// } // -// } -// } -// // do the projection -// DONE: -// if(connection){ -// coefficents[2]=room->GetZPos()*0 + projection.Norm()*tan(theta); -// } +// } +// } +// // do the projection +// DONE: +// if(connection){ +// coefficents[2]=room->GetZPos()*0 + projection.Norm()*tan(theta); +// } // -// } -// else -// { // we are having a stair -// //return; -//// cout<<"area: " <<stair->GetArea()<<endl; -//// if(stair->GetArea()<StairAreaToIgnore) { -//// return; -//// } -//// if(stair->GetAllCrossings().size()==2) return; +// } +// else +// { // we are having a stair +// //return; +//// cout<<"area: " <<stair->GetArea()<<endl; +//// if(stair->GetArea()<StairAreaToIgnore) { +//// return; +//// } +//// if(stair->GetAllCrossings().size()==2) return; // -// // looking for the normal vector -// Point A; -// Point B; -// Point C; -// Point D; -// bool finished=false; -// const vector<Point>& poly=sub->GetPolygon(); -// //loop until we get something -// while ( ! finished) { +// // looking for the normal vector +// Point A; +// Point B; +// Point C; +// Point D; +// bool finished=false; +// const vector<Point>& poly=sub->GetPolygon(); +// //loop until we get something +// while ( ! finished) { // -// for (unsigned int i1=0;i1<4;i1++){ +// 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)); -// double dist2= Line(p3,p4).DistTo(Point(0,0)); -// 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; -// }else { -// A=p1; -// B=p4; -// C=p3; -// D=p2; -// } -// finished=true; -// }else {cout<<"dist: " <<dist2<<endl;} -// } -// } -// } +// 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)); +// double dist2= Line(p3,p4).DistTo(Point(0,0)); +// 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; +// }else { +// A=p1; +// B=p4; +// C=p3; +// D=p2; +// } +// finished=true; +// }else {cout<<"dist: " <<dist2<<endl;} +// } +// } +// } // -// double base=room->GetZPos(); +// double base=room->GetZPos(); // -// double vecDA[3]; -// vecDA[0]= (A-D).pX; -// vecDA[1]= (A-D).pY; -// vecDA[2]= 0.0; +// double vecDA[3]; +// vecDA[0]= (A-D).pX; +// vecDA[1]= (A-D).pY; +// vecDA[2]= 0.0; // -// double vecDC[3]; -// vecDC[0]= (C-D).pX; -// vecDC[1]= (C-D).pY; -// vecDC[2]= (C-D).Norm()*cos(theta); +// double vecDC[3]; +// vecDC[0]= (C-D).pX; +// vecDC[1]= (C-D).pY; +// vecDC[2]= (C-D).Norm()*cos(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]; +// 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]; // // -// // the equation of the plan is given as: Ax+By+Cz+d=0; -// // using the Point A: -// double d = - (vecNormal[0]*A.pX+vecNormal[1]*A.pY+vecNormal[2]*base); -// coefficents[0]= - vecNormal[0] / vecNormal[2]; -// coefficents[1]= - vecNormal[1] / vecNormal[2]; -// coefficents[2]= - d / vecNormal[2]; -// } +// // the equation of the plan is given as: Ax+By+Cz+d=0; +// // using the Point A: +// double d = - (vecNormal[0]*A.pX+vecNormal[1]*A.pY+vecNormal[2]*base); +// coefficents[0]= - vecNormal[0] / vecNormal[2]; +// coefficents[1]= - vecNormal[1] / vecNormal[2]; +// coefficents[2]= - d / vecNormal[2]; +// } // //} 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; - } - } - } - } + //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; + } + } + } + } } 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() ); - } + //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; - // } - } - } - } - - - - 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]); - } - } - } + 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; + // } + } + } + } + + + + 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; + int nLine=0; - 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(); - //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; + 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(); + //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!"); + 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; + return _edges; } const std::vector<NavMesh::JNode*>& NavMesh::GetNodes() const { - return _nodes; + return _nodes; } const std::vector<NavMesh::JObstacle*>& NavMesh::GetObst() const { - return _obst; + return _obst; } const std::vector<NavMesh::JVertex*>& NavMesh::GetVertices() const { - return _vertices; + return _vertices; } diff --git a/routing/NavMesh.h b/routing/NavMesh.h index e6b2cfcb5463465b9a51e281cbe5b7f49f88b032..e22f00333539df6b760dccd7bcf98ac31c587ff3 100644 --- a/routing/NavMesh.h +++ b/routing/NavMesh.h @@ -27,239 +27,239 @@ 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++; - } - 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; + 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++; + } + 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 a908b351a7d30b27541016f5ad0bd5bc6e626b10..aab9c497d53e9edce9e7e8a5579c02e8795f565f 100644 --- a/routing/QuickestPathRouter.cpp +++ b/routing/QuickestPathRouter.cpp @@ -43,1002 +43,1002 @@ QuickestPathRouter::~QuickestPathRouter() { } 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); - } - - // 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=="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; + 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"); + + string nav_line_file=""; + + for(TiXmlElement* e = xRouters->FirstChildElement("router"); e; + e = e->NextSiblingElement("router")) { + + 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; } 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 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); + 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; + 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 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; + return 1.0/time; } // based on jam only //int QuickestPathRouter::GetQuickestRoute(Pedestrian*ped, AccessPoint* nearestAP){ // -// // uncomment this line to get the standard global shortest path -// //return nearestAP->GetNextApTo(ped->GetFinalDestination()); +// // uncomment this line to get the standard global shortest path +// //return nearestAP->GetNextApTo(ped->GetFinalDestination()); // -// int quickest=-1; -// double minJam=FLT_MAX; -// //first return the result based on congestion +// int quickest=-1; +// double minJam=FLT_MAX; +// //first return the result based on congestion // -// // 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: delete not relevant alternatives +// //TODO: delete not relevant alternatives // -// for(unsigned int ap=0;ap<aps.size();ap++){ +// for(unsigned int ap=0;ap<aps.size();ap++){ // -// // this wont be necessary if you have directed graph -// double dist1=aps[ap]->GetDistanceTo(ped->GetFinalDestination()); -// double dist2=nearestAP->GetDistanceTo(ped->GetFinalDestination()); -// if(dist1>=dist2) continue; +// // this wont be necessary if you have directed graph +// double dist1=aps[ap]->GetDistanceTo(ped->GetFinalDestination()); +// double dist2=nearestAP->GetDistanceTo(ped->GetFinalDestination()); +// if(dist1>=dist2) continue; // -// double jam=GetJamSizeAtExit(aps[ap]->GetID()); -// if(jam<=minJam){ -// minJam=jam; -// quickest=aps[ap]->GetID(); -// } -// } +// double jam=GetJamSizeAtExit(aps[ap]->GetID()); +// if(jam<=minJam){ +// minJam=jam; +// quickest=aps[ap]->GetID(); +// } +// } // -// // return the one with the lowest jam size -// return quickest; +// // return the one with the lowest jam size +// return quickest; //} //TODO: exclude myself from the jam computations //double QuickestPathRouter::GetJamSizeAtExit(int exitID){ -// double result=0.0; -// double jamThreshold=0.5; -// //lazy version of the implementation +// double result=0.0; +// double jamThreshold=0.5; +// //lazy version of the implementation // -// // get the connecting rooms -// // cant do this with the APs, need subrooms -// SubRoom* sbr1 = _building->GetGoal(exitID)->GetSubRoom1(); -// SubRoom* sbr2 = _building->GetGoal(exitID)->GetSubRoom2(); +// // get the connecting rooms +// // cant do this with the APs, need subrooms +// SubRoom* sbr1 = _building->GetGoal(exitID)->GetSubRoom1(); +// SubRoom* sbr2 = _building->GetGoal(exitID)->GetSubRoom2(); // -// _accessPoints[exitID]->Get +// _accessPoints[exitID]->Get // -// if (sbr1){ -// 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().Norm()<jamThreshold){ -// result+=ped->GetEllipse().GetArea(); -// } -// } -// } -// } +// if (sbr1){ +// 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().Norm()<jamThreshold){ +// result+=ped->GetEllipse().GetArea(); +// } +// } +// } +// } // -// if (sbr2){ -// 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().Norm()<jamThreshold){ -// result+=ped->GetEllipse().GetArea(); -// } -// } -// } -// } +// if (sbr2){ +// 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().Norm()<jamThreshold){ +// result+=ped->GetEllipse().GetArea(); +// } +// } +// } +// } // -// // get the pedestrians with destination exitID +// // get the pedestrians with destination exitID // -// // check the velocities +// // check the velocities // -// // compute the areas -// return result; +// // compute the areas +// return result; //} 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(); - - // 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 - - 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; - */ - - - //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); - } - - // 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]); - } - } - - //clear double links - CheckAndClearDoubleLinkedNodes(); + 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(); + + //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]; + + /* 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); + } + + //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); + // + // } + } + + // 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(); } 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); - } - } - } - } + 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]); - } - - } + 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){ - Log->Write("INFO:\tInit Quickest Path Router Engine"); - GlobalRouter::Init(building); - - // 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); - - // exit(0); - Log->Write("INFO:\tDone with Quickest Path Router Engine!"); + Log->Write("INFO:\tInit Quickest Path Router Engine"); + GlobalRouter::Init(building); + + // 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); + + // 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); - } + *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(); + 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){ - 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){ - 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){ - //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){ - //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); - } - } + 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 046ed999478f08f39ac049502c77107960d0ed8e..b486799cd5d10a2aa2e4c73f15457b88a08abf66 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 8a470298465cca413fb56d78802c50cc6ae526ff..def30c8cbd2c4ccbba0037dab233a29e19bf4821 100644 --- a/routing/Router.cpp +++ b/routing/Router.cpp @@ -33,68 +33,68 @@ using namespace std; Router::Router() { - _trips = vector<vector<int> >(); - _finalDestinations = vector<int>(); - _id=-1; - _strategy=ROUTING_UNDEFINED; + _trips = vector<vector<int> >(); + _finalDestinations = vector<int>(); + _id=-1; + _strategy=ROUTING_UNDEFINED; } 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); - } + 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); + _trips.push_back(trip); } void Router::AddFinalDestinationID(int id) { - _finalDestinations.push_back(id); + _finalDestinations.push_back(id); } const vector<int> Router::GetFinalDestinations() const { - return _finalDestinations; + return _finalDestinations; } void Router::SetID(int id) { - _id=id; + _id=id; } int Router::GetID() const { - return _id; + return _id; } void Router::SetStrategy(RoutingStrategy strategy) { - _strategy=strategy; + _strategy=strategy; } RoutingStrategy Router::GetStrategy() const { - return _strategy; + return _strategy; } void Router::WriteToErrorLog() const { - //TODO -// for (map<int, Crossing*>::const_iterator iter = pCrossings.begin(); -// iter != pCrossings.end(); ++iter) { -// iter->second->WriteToErrorLog(); -// } -// for (map<int, Transition*>::const_iterator iter = pTransitions.begin(); -// iter != pTransitions.end(); ++iter) { -// iter->second->WriteToErrorLog(); -// } -// for (map<int, Hline*>::const_iterator iter = pHlines.begin(); -// iter != pHlines.end(); ++iter) { -// iter->second->WriteToErrorLog(); -// } + //TODO +// for (map<int, Crossing*>::const_iterator iter = pCrossings.begin(); +// iter != pCrossings.end(); ++iter) { +// iter->second->WriteToErrorLog(); +// } +// for (map<int, Transition*>::const_iterator iter = pTransitions.begin(); +// iter != pTransitions.end(); ++iter) { +// iter->second->WriteToErrorLog(); +// } +// for (map<int, Hline*>::const_iterator iter = pHlines.begin(); +// iter != pHlines.end(); ++iter) { +// iter->second->WriteToErrorLog(); +// } } diff --git a/routing/Router.h b/routing/Router.h index 8576e596dfcd87e919877a1d253d752a843ad488..9d94ec4f0ed393f685787b3cc9e89f48c143800a 100644 --- a/routing/Router.h +++ b/routing/Router.h @@ -27,7 +27,7 @@ */ #ifndef _ROUTER_H -#define _ROUTER_H +#define _ROUTER_H #include <vector> @@ -38,93 +38,93 @@ class Pedestrian; class Router { -private: - /// routing strategy as defined in the Macros.h file - RoutingStrategy _strategy; + private: + /// routing strategy as defined in the Macros.h file + RoutingStrategy _strategy; - /// the id as present in the persons.xml file - int _id; + /// the id as present in the persons.xml file + int _id; -protected: + protected: - /// Contain the ids of the intermediate destinations - std::vector<std::vector<int> >_trips; + /// Contain the ids of the intermediate destinations + std::vector<std::vector<int> >_trips; - /// All final destinations of the pedestrians - std::vector<int> _finalDestinations; + /// All final destinations of the pedestrians + std::vector<int> _finalDestinations; -public: - Router(); + public: + Router(); - virtual ~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 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); + /** + * 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; + /** + * 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; + /** + * @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); + /** + * 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; + /** + * @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. + */ + void SetStrategy(RoutingStrategy strategy); - /** - * The strategy is automatically set based on the description in the - * person file. - */ - RoutingStrategy GetStrategy() const; + /** + * The strategy is automatically set based on the description in the + * person file. + */ + RoutingStrategy GetStrategy() const; - /** - * Debug output for this class - */ - void WriteToErrorLog() 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; + /** + * 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; + /** + * 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; }; -#endif /* _ROUTING_H */ +#endif /* _ROUTING_H */ diff --git a/routing/RoutingEngine.cpp b/routing/RoutingEngine.cpp index 7ff459093c4e0e203603be19843cce0bc87d285e..bb765eb2efd47a2bf2380f47a4aec644c26c758e 100644 --- a/routing/RoutingEngine.cpp +++ b/routing/RoutingEngine.cpp @@ -16,69 +16,69 @@ RoutingEngine::RoutingEngine() { } RoutingEngine::~RoutingEngine() { - for(unsigned int r=0;r<_routersCollection.size();r++){ - delete _routersCollection[r]; - } - _routersCollection.clear(); + 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); - } + for(unsigned int r=0;r<_routersCollection.size();r++){ + _routersCollection[r]->AddFinalDestinationID(id); + } } void RoutingEngine::FindRoute(Pedestrian* ped) { - ped->FindRoute(); + 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); + 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); - } + 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; + 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; + 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); + _tripsCollection.push_back(trip); } void RoutingEngine::Init(Building* building) { - for(unsigned int r=0;r<_routersCollection.size();r++){ - _routersCollection[r]->Init(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 cedba0c37676da9738ab8164ee2e3417be8fd421..92cc9adfddc9f11db5de48721e083da6813af842 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 54eeed9e40572ca75821de38f52e30323b4575de..34912c78ec369fd61d489803035283a7a7e8158e 100644 --- a/routing/SafestPathRouter.cpp +++ b/routing/SafestPathRouter.cpp @@ -44,205 +44,205 @@ 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() { - // 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] << " "; - - //} + //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) { - 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; + 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(); - - } - } - } + 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(); - } - } - } - */ + /* + 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(); + } + } + } + */ } @@ -252,126 +252,126 @@ void SafestPathRouter::UpdateMatrices(){ int SafestPathRouter::ComputeSafestPath(Pedestrian* p) { -// // adjust the update frequency -// double diff= fabs((int)p->GetGlobalTime() - p->GetGlobalTime()); -// if (diff>0.015) return -1; -// if((((int)p->GetGlobalTime())%UPDATE_FREQUENCY)!=0) return -1; +// // adjust the update frequency +// double diff= fabs((int)p->GetGlobalTime() - p->GetGlobalTime()); +// 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") -// { -// cout << path[j]->GetSubRoomID()<< " "; -// cout << endl; -// } +// for(unsigned int j = 0; j <path.size(); j++) +// //if(path[j]->GetType()=="floor") +// { +// cout << path[j]->GetSubRoomID()<< " "; +// cout << endl; +// } - // 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(); -// if (p->GetRoomID()==0 && p->GetSubRoomID()==2) -// { -// p->SetFinalDestination(0); -// } +// if (p->GetRoomID()==0 && p->GetSubRoomID()==2) +// { +// p->SetFinalDestination(0); +// } // -// if (p->GetRoomID()==0 && p->GetSubRoomID()==3) -// { -// p->SetFinalDestination(1); -// } +// if (p->GetRoomID()==0 && p->GetSubRoomID()==3) +// { +// p->SetFinalDestination(1); +// } //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") -// { -// std::vector<SubRoom*> path; -// GetPath(p, 1, path); -// preSub=new double [path.size()]; -// for (unsigned int i=0; i<path.size(); i++){ -// preSub[i]=path[i]->GetSubRoomID(); -// for(int j = 0; j <path.size(); j++) -// cout << preSub[j]<< " "; -// cout << endl; +// Room* room = _building->GetRoom(i); +// for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { +// SubRoom* sub = room->GetSubRoom(j); +// if(sub->GetType()=="floor") +// { +// std::vector<SubRoom*> path; +// GetPath(p, 1, path); +// preSub=new double [path.size()]; +// for (unsigned int i=0; i<path.size(); i++){ +// preSub[i]=path[i]->GetSubRoomID(); +// for(int j = 0; j <path.size(); j++) +// cout << preSub[j]<< " "; +// cout << endl; // -// } -// } -// } -// } +// } +// } +// } +// } // Printing a matrix //cout <<"total distance: " <<distance<<endl; @@ -390,7 +390,7 @@ 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(); } @@ -399,7 +399,7 @@ int SafestPathRouter::GetAgentsCountInSubroom( int roomID, int subroomID) //todo: use ? void SafestPathRouter::Initialize(){ - //ReadMatrixFromFDS(); + //ReadMatrixFromFDS(); } @@ -408,63 +408,63 @@ 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 +473,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,157 +520,157 @@ 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); - } - - // 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(){ - //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; @@ -679,142 +679,142 @@ void SafestPathRouter::MappingFloorIDtoIndex(){ 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) { +// for (unsigned int p = 0; p < pedestrians.size(); ++p) { // -// if (pedestrians[p]->FindRoute() == -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); -// } -// } +// if (pedestrians[p]->FindRoute() == -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); +// } +// } } /* - std::vector<SubRoom*> path; - GetPath(p, 1, path); + std::vector<SubRoom*> path; + GetPath(p, 1, path); - double dF[path.size()]; - double fF=0; + double dF[path.size()]; + double fF=0; - for(unsigned i=0; i<path.size(); i++) - dF[i]=0; + for(unsigned i=0; i<path.size(); i++) + dF[i]=0; - for(unsigned j = 0; j <path.size(); j++) - { - int i=preSub[j]; - dF[j]=rR[i]; + for(unsigned j = 0; j <path.size(); j++) + { + int i=preSub[j]; + dF[j]=rR[i]; - // for(int j = 0; j < numberOfSubroom; j++) - // cout <<i<<endl; + // for(int j = 0; j < numberOfSubroom; j++) + // cout <<i<<endl; - } + } - //for(int j = 0; j < path.size(); j++) - // cout << dF[j] << " "; - //cout << endl; + //for(int j = 0; j < path.size(); j++) + // cout << dF[j] << " "; + //cout << endl; - //for(int j=0; j<path.size(); j++) - // fF=fF+dF[j]; + //for(int j=0; j<path.size(); j++) + // fF=fF+dF[j]; - fF=fF-dF[1]; + fF=fF-dF[1]; - //cout << fF<<endl; + //cout << fF<<endl; - // Print out final distance matrix - // for(int j = 0; j < numberOfSubroom; j++) - // cout << i<<endl; + // Print out final distance matrix + // for(int j = 0; j < numberOfSubroom; j++) + // cout << i<<endl; } - // Floyd-Warchal algorithm is going here - // Initialize - int vertices = numberOfSubroom; - vector<vector<double> > a(vertices, vector<double>(vertices,999)); - // initialize diagonal - for(int i=0; i < vertices; i++) - a[i][i]=0; + // Floyd-Warchal algorithm is going here + // Initialize + int vertices = numberOfSubroom; + vector<vector<double> > a(vertices, vector<double>(vertices,999)); + // initialize diagonal + for(int i=0; i < vertices; i++) + a[i][i]=0; - // initialize distances - a[0][1]=rR[0]; - a[1][2]=rR[1]; - a[1][3]=rR[2]; - // - a[1][0]=rR[0]; - a[2][1]=rR[1]; - a[3][1]=rR[2]; + // initialize distances + a[0][1]=rR[0]; + a[1][2]=rR[1]; + a[1][3]=rR[2]; + // + a[1][0]=rR[0]; + a[2][1]=rR[1]; + a[3][1]=rR[2]; - // Floyd-Warshal - // Add nodes between (first 1 then 2, 3 till n) and look if - // distance is shorter - for(int k = 0; k < vertices; k++) - for(int i = 0; i < vertices; i++) - for(int j = 0; j < vertices; j++) - if(a[i][j]>a[i][k]+a[k][j]) - a[i][j]=a[i][k]+a[k][j]; + // Floyd-Warshal + // Add nodes between (first 1 then 2, 3 till n) and look if + // distance is shorter + for(int k = 0; k < vertices; k++) + for(int i = 0; i < vertices; i++) + for(int j = 0; j < vertices; j++) + if(a[i][j]>a[i][k]+a[k][j]) + a[i][j]=a[i][k]+a[k][j]; */ @@ -825,109 +825,109 @@ void SafestPathRouter::ComputeAndUpdateDestinations( - //Print out final distance matrix - //for(int i = 0; i < vertices; i++){ - // for(int j = 0; j < vertices; j++) - // cout << a[i][j] << " "; - // cout << endl; - // cout<<p->GetGlobalTime()<<endl; - // } - //double g3_0=a[0][2];// From node 3 to 0 (0 is the goal O) - //double g3_1=a[1][2];// From node 3 to 1 (1 is the goal 1) - //double g1_3=a[0][2]; - //double g1_4=a[0][3]; - //cout<<"The g5_0: "<<g5_0<<"\n"; - //cout<<"The g5_1: "<<g5_1<<"\n"; - //cout<<p->GetGlobalTime()<<endl; + //Print out final distance matrix + //for(int i = 0; i < vertices; i++){ + // for(int j = 0; j < vertices; j++) + // cout << a[i][j] << " "; + // cout << endl; + // cout<<p->GetGlobalTime()<<endl; + // } + //double g3_0=a[0][2];// From node 3 to 0 (0 is the goal O) + //double g3_1=a[1][2];// From node 3 to 1 (1 is the goal 1) + //double g1_3=a[0][2]; + //double g1_4=a[0][3]; + //cout<<"The g5_0: "<<g5_0<<"\n"; + //cout<<"The g5_1: "<<g5_1<<"\n"; + //cout<<p->GetGlobalTime()<<endl; - bool a1 = true; + bool a1 = true; - while (a1 == true) - { + while (a1 == true) + { - if (g5_0>=g5_1) - { - p->SetFinalDestination(1); - p->ClearMentalMap(); + if (g5_0>=g5_1) + { + p->SetFinalDestination(1); + p->ClearMentalMap(); - } - else - { - p->SetFinalDestination(0); - p->ClearMentalMap(); - a1=false; - } - } - } + } + else + { + p->SetFinalDestination(0); + p->ClearMentalMap(); + a1=false; + } + } + } - 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); - int room; - } - } + 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); + int room; + } + } - int roomID=p->GetRoomID(); - int subroomID=p->GetSubRoomID(); - int nGoals =_building->GetNumberOfGoals(); + int roomID=p->GetRoomID(); + int subroomID=p->GetSubRoomID(); + int nGoals =_building->GetNumberOfGoals(); - rR[subroomID][subroomID]= + rR[subroomID][subroomID]= - //if (p->GetRoomID()==0 && p->GetSubRoomID()==0) - { - if (g1_3>=g1_4) - { - p->SetFinalDestination(1); - p->ClearMentalMap(); - } - else - { - p->SetFinalDestination(0); - p->ClearMentalMap(); - } - } + //if (p->GetRoomID()==0 && p->GetSubRoomID()==0) + { + if (g1_3>=g1_4) + { + p->SetFinalDestination(1); + p->ClearMentalMap(); + } + else + { + p->SetFinalDestination(0); + p->ClearMentalMap(); + } + } } - int roomID=p->GetRoomID(); - int subroomID=p->GetSubRoomID(); - int nGoals =_building->GetNumberOfGoals(); + int roomID=p->GetRoomID(); + int subroomID=p->GetSubRoomID(); + int nGoals =_building->GetNumberOfGoals(); if (p->GetID()==1) - { - if (g5_0>=g5_1) - { - p->SetFinalDestination(1); - p->ClearMentalMap(); // reset the destination - //cout<<"The g5_0 is the best: "<< g5_0 <<"\n"; - } - else{ - p->SetFinalDestination(0); - p->ClearMentalMap(); // reset the destination - //cout<<"The g5_1 is the best: "<< g5_1 <<"\n"; - } - } - //if (p->GetRoomID()==0 && p->GetSubRoomID()==2) - //cout<<p->GetGlobalTime()<<endl; - - - if (p->GetRoomID()==6 && p->GetSubRoomID()==6) - { - int TotalNumberofPedInsection; - // p->SetFinalDestination(0); - int TotalNumberofPedInSection2=_building->GetRoom(p->GetRoomID())->GetSubRoom(p->GetSubRoomID())->GetAllPedestrians().size(); - TotalNumberofPedInSection=TotalNumberofPedInsection2; - cout<<TotalNumberofPedInSection<<endl; - cout<<p->GetGlobalTime()<<endl; - } + { + if (g5_0>=g5_1) + { + p->SetFinalDestination(1); + p->ClearMentalMap(); // reset the destination + //cout<<"The g5_0 is the best: "<< g5_0 <<"\n"; + } + else{ + p->SetFinalDestination(0); + p->ClearMentalMap(); // reset the destination + //cout<<"The g5_1 is the best: "<< g5_1 <<"\n"; + } + } + //if (p->GetRoomID()==0 && p->GetSubRoomID()==2) + //cout<<p->GetGlobalTime()<<endl; + + + if (p->GetRoomID()==6 && p->GetSubRoomID()==6) + { + int TotalNumberofPedInsection; + // p->SetFinalDestination(0); + int TotalNumberofPedInSection2=_building->GetRoom(p->GetRoomID())->GetSubRoom(p->GetSubRoomID())->GetAllPedestrians().size(); + TotalNumberofPedInSection=TotalNumberofPedInsection2; + cout<<TotalNumberofPedInSection<<endl; + cout<<p->GetGlobalTime()<<endl; + } } */ diff --git a/routing/SafestPathRouter.h b/routing/SafestPathRouter.h index 60ec3043cf04bf7c8652e85e79670273f2b6a75d..99427dddca29214d9831e52234682d46f4484d30 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 bcdd76e244c7e50d63d4708982c22070946216ae..8208e8fc5301a6a8bd35bfcf649ae8a484344346 100644 --- a/routing/Triangulation.h +++ b/routing/Triangulation.h @@ -25,83 +25,83 @@ 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(); + 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; + 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 1bcaa0f8cfb46970851ca31df0ae0d339729f71a..4bad4335aa99f70b46c5e749a2ab9876ad059913 100644 --- a/routing/cognitive_map/AbstractCognitiveMapCreator.h +++ b/routing/cognitive_map/AbstractCognitiveMapCreator.h @@ -17,14 +17,14 @@ class CognitiveMap; class AbstractCognitiveMapCreator { -public: - AbstractCognitiveMapCreator(const Building * b) : building(b) {} + 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.h b/routing/cognitive_map/CognitiveMap.h index 8c465f8916e954db47bb9b2317f397fde0b13d1c..d3fb08c946d8589953264d6ef889b80ce40d00a5 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.h b/routing/cognitive_map/CognitiveMapStorage.h index 60134eb4e818a8b8b5c753863efe9b6e21f04a57..3a63705e21253ddb9cd6145a6912f6880db254d7 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.h b/routing/cognitive_map/CompleteCognitiveMapCreator.h index bace839bcbb7cbbca4c65420aa7b3e73b954138b..46df1549dfadfba0ddacda304f4d246933a06c08 100644 --- a/routing/cognitive_map/CompleteCognitiveMapCreator.h +++ b/routing/cognitive_map/CompleteCognitiveMapCreator.h @@ -19,13 +19,13 @@ class Building; 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.h b/routing/cognitive_map/EmptyCognitiveMapCreator.h index ae7719ae2632b72c5d1da2e99a56fd5556d125de..69d30459d42b20e7244ce658a5e8b47e649ee529 100644 --- a/routing/cognitive_map/EmptyCognitiveMapCreator.h +++ b/routing/cognitive_map/EmptyCognitiveMapCreator.h @@ -19,13 +19,13 @@ class Building; 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.h b/routing/cognitive_map/NavigationGraph.h index a1bbf20ab8175603ff09e5d90ce392c00342ed20..5bca7bce320970ccce1ebf7523c7e8c43cfdab00 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.h b/routing/cognitive_map/navigation_graph/GraphEdge.h index 2c9bcaeab6bf79cc303d74272d257026a2c00c97..6ef3565090f52d8a16515a08c802111ca74f9b62 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.h b/routing/cognitive_map/navigation_graph/GraphVertex.h index 7765606685953e1ea25899ef6479916f1f19c559..41ef576bbdd887987e9d4b084461ef61abe499a7 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 b19988cbb3ad18b5083f2792abef48555cb283da..4f54aa2633af29475b0d51cc6874fd077f6b75ea 100644 --- a/routing/cognitive_map/sensor/AbstractSensor.h +++ b/routing/cognitive_map/sensor/AbstractSensor.h @@ -18,14 +18,14 @@ 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; + 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.h b/routing/cognitive_map/sensor/RoomToFloorSensor.h index 4eee5f6ba25e16cb659ec3f342704215835c89b9..8b38d4a0723e7f9984e38468d66492943ae4c326 100644 --- a/routing/cognitive_map/sensor/RoomToFloorSensor.h +++ b/routing/cognitive_map/sensor/RoomToFloorSensor.h @@ -15,14 +15,14 @@ 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.h b/routing/cognitive_map/sensor/SensorManager.h index 78c336c3da1f1b81c67b635ce25a22947149db9c..b2e7b3b857500b665dff801bdee5c8c04170f062 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 856bb96d512fbf9d241b3755a669217a282970fb..6ee541736254bbb4cc046387be5f0e87c11755c5 100644 --- a/routing/graph/NavLineState.cpp +++ b/routing/graph/NavLineState.cpp @@ -38,8 +38,8 @@ bool NavLineState::isShareable(double time) { if(!timeOfInformation) return true; if(timeOfInformation+INFO_OFFSET < time) { - timeOfInformation = 0; - return true; + timeOfInformation = 0; + return true; } return false; @@ -49,10 +49,10 @@ bool NavLineState::isShareable(double time) bool NavLineState::mergeDoor(NavLineState & orig, double time) { if(timeFirstSeen == 0 || orig.timeFirstSeen > timeFirstSeen) { - open = orig.open; - timeFirstSeen = orig.timeFirstSeen; - timeOfInformation = time; - return true; + open = orig.open; + timeFirstSeen = orig.timeFirstSeen; + timeOfInformation = time; + return true; } return false; } diff --git a/routing/graph/NavLineState.h b/routing/graph/NavLineState.h index 7f8ba9afb8d653363106a86da3b0076d42fe88a6..fb88612b47095f7fc4c72be495eb29d10530bc9d 100644 --- a/routing/graph/NavLineState.h +++ b/routing/graph/NavLineState.h @@ -18,20 +18,20 @@ class NavLineState { -public: - NavLineState(); - ~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 + 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 d4c511d058700f46cba0e162f2ad7b3d244b9667..30bb799c127478e11bda41a547ac505a7651bb69 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,19 +455,19 @@ 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; + } }; /**************************************** @@ -475,16 +475,16 @@ Vertex * RoutingGraph::GetVertex(int id) ***************************************/ 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; + 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 +494,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 7abfe4524d64a5490e99cd7e80f254c538fd7ab5..02e179050d010453548e6720f27c93bd48194691 100644 --- a/routing/graph/RoutingGraph.h +++ b/routing/graph/RoutingGraph.h @@ -30,56 +30,56 @@ 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); }; @@ -88,38 +88,38 @@ private: struct Edge { public: - Vertex * dest; - Vertex * src; - double distance; - SubRoom * sub; + Vertex * dest; + Vertex * src; + double distance; + SubRoom * sub; }; 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 { 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.h b/routing/graph/RoutingGraphStorage.h index 34648bde2fecdb1a60b9f49b8b360e2bb02ed093..f8a06d40ac7f29d2ccf4156617dcda0a32f60db3 100644 --- a/routing/graph/RoutingGraphStorage.h +++ b/routing/graph/RoutingGraphStorage.h @@ -16,25 +16,25 @@ class RoutingGraphStorage { -public: - RoutingGraphStorage(); - ~RoutingGraphStorage(); - void init(Building * b); - RoutingGraph * GetGraph(std::set<int> closed_doors); + 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; + 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>()); + /** + * @param iset + * @param from + */ + void GenerateNewGraph(std::set<int> iset, std::set<int> from = std::set<int>()); diff --git a/routing/mesh/Mesh.cpp b/routing/mesh/Mesh.cpp index 55ca56f71d1f37a643692811b66c5ad68c02baba..3d628697b5803d86e4acab39f31572a6cf807f37 100644 --- a/routing/mesh/Mesh.cpp +++ b/routing/mesh/Mesh.cpp @@ -9,142 +9,142 @@ #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); + _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; + //delete[] _normvec; } MeshCellGroup::MeshCellGroup(std::string groupname,std::vector<MeshCell*> cells){ - _groupname=groupname; - _cells=cells; + _groupname=groupname; + _cells=cells; } MeshCellGroup::~MeshCellGroup(){ - for(unsigned int i=0;i<_cells.size();i++) - delete _cells[i]; + for(unsigned int i=0;i<_cells.size();i++) + delete _cells[i]; } std::vector<MeshCell*> MeshCellGroup::GetCells()const{ - return _cells; + return _cells; } MeshData::MeshData(){ - _mNodes=std::vector<Point*>(); - _mEdges=std::vector<MeshEdge*>(); - _mObstacles=std::vector<MeshEdge*>(); - _mCellGroups=std::vector<MeshCellGroup*>(); - _mCellCount=0; + _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]; + 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 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; - } + 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; + 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){ - is>>mn._x>>mn._y; - return is; + is>>mn._x>>mn._y; + return is; } */ diff --git a/routing/mesh/Mesh.h b/routing/mesh/Mesh.h index 9a89204e86a17c4a6a989e1e1da5ff57f0ec5a24..70340a91cfa0e3efc5d82d9b38fef8eb6b901391 100644 --- a/routing/mesh/Mesh.h +++ b/routing/mesh/Mesh.h @@ -20,76 +20,76 @@ 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;}; + 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 + 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 + 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; + 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 066576820516de3bae97b08f9258468f9cc136f4..186b06c81f2b38043540e4f6fb21444d13f7261d 100644 --- a/tinyxml/tinystr.cpp +++ b/tinyxml/tinystr.cpp @@ -36,76 +36,76 @@ 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; } -#endif // TIXML_USE_STL +#endif // TIXML_USE_STL diff --git a/tinyxml/tinystr.h b/tinyxml/tinystr.h index 89cca3341564c0337e3e940bfa4ae053e84e656c..db5b5130729cfa2f2ce1f081ea7e100ccdb4ad77 100644 --- a/tinyxml/tinystr.h +++ b/tinyxml/tinystr.h @@ -1,24 +1,24 @@ /* -www.sourceforge.net/projects/tinyxml + www.sourceforge.net/projects/tinyxml -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. + 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 -redistribute it freely, subject to the following restrictions: + 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 -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. + 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 -must not be misrepresented as being the original software. + 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 -distribution. + 3. This notice may not be removed or altered from any source + distribution. */ @@ -30,236 +30,236 @@ distribution. #include <assert.h> #include <string.h> -/* The support for explicit isn't that universal, and it isn't really - required - it is used to check that the TiXmlString class isn't incorrectly - used. Be nice to old compilers and macro it here: +/* The support for explicit isn't that universal, and it isn't really + required - it is used to check that the TiXmlString class isn't incorrectly + used. Be nice to old compilers and macro it here: */ #if defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - #define TIXML_EXPLICIT explicit +// Microsoft visual studio, version 6 and higher. +#define TIXML_EXPLICIT explicit #elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - #define TIXML_EXPLICIT explicit +// GCC version 3 and higher.s +#define TIXML_EXPLICIT explicit #else - #define TIXML_EXPLICIT +#define TIXML_EXPLICIT #endif /* - TiXmlString is an emulation of a subset of the std::string template. - Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. - Only the member functions relevant to the TinyXML project have been implemented. - 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. + TiXmlString is an emulation of a subset of the std::string template. + Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. + Only the member functions relevant to the TinyXML project have been implemented. + 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_; + 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); } @@ -278,28 +278,28 @@ 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. + 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; - } + public : + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const TiXmlString & in) + { + *this += in; + return *this; + } + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const char * in) + { + *this += in; + return *this; + } } ; -#endif // TIXML_STRING_INCLUDED -#endif // TIXML_USE_STL +#endif // TIXML_STRING_INCLUDED +#endif // TIXML_USE_STL diff --git a/tinyxml/tinyxml.cpp b/tinyxml/tinyxml.cpp index 9c161dfcb934e855ff679998c34669bfdd66aa21..719e460469227f5405cf40a7cd0961069f6424d3 100644 --- a/tinyxml/tinyxml.cpp +++ b/tinyxml/tinyxml.cpp @@ -38,670 +38,670 @@ 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* 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; - } + 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 ) + : 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,1178 +709,1178 @@ 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 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; + tabsize = 4; + useMicrosoftBOM = false; value = documentName; - ClearError(); + 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; } /* TiXmlAttribute* TiXmlAttribute::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; + // 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; } */ 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; } /* TiXmlAttribute* TiXmlAttribute::Previous() { - // 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; } */ void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const { - TIXML_STRING n, v; + TIXML_STRING n, v; - EncodeString( name, &n ); - EncodeString( value, &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) += "'"; - } - } + 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 ) +TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, + 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 ( 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 ( !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 + 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 b3f08d658abb934b968d4ff57c97b7686b3ef207..cae887139b2e80a9f535c6d17aa056f0fcd7ae3c 100644 --- a/tinyxml/tinyxml.h +++ b/tinyxml/tinyxml.h @@ -1,25 +1,25 @@ /* -www.sourceforge.net/projects/tinyxml -Original code by Lee Thomason (www.grinninglizard.com) + 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 -damages arising from the use of this software. + 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 -redistribute it freely, subject to the following restrictions: + 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 -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. + 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 -must not be misrepresented as being the original software. + 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 -distribution. + 3. This notice may not be removed or altered from any source + distribution. */ @@ -46,13 +46,13 @@ distribution. #endif #ifdef TIXML_USE_STL - #include <string> - #include <iostream> - #include <sstream> - #define TIXML_STRING std::string +#include <string> +#include <iostream> +#include <sstream> +#define TIXML_STRING std::string #else - #include "tinystr.h" - #define TIXML_STRING TiXmlString +#include "tinystr.h" +#define TIXML_STRING TiXmlString #endif // Deprecated library function hell. Compilers want to use the @@ -62,25 +62,25 @@ distribution. #define TIXML_SAFE #ifdef TIXML_SAFE - #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - // Microsoft visual studio, version 2005 and higher. - #define TIXML_SNPRINTF _snprintf_s - #define TIXML_SSCANF sscanf_s - #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - //#pragma message( "Using _sn* functions." ) - #define TIXML_SNPRINTF _snprintf - #define TIXML_SSCANF sscanf - #elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - //#warning( "Using sn* functions." ) - #define TIXML_SNPRINTF snprintf - #define TIXML_SSCANF sscanf - #else - #define TIXML_SNPRINTF snprintf - #define TIXML_SSCANF sscanf - #endif -#endif +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) +// Microsoft visual studio, version 2005 and higher. +#define TIXML_SNPRINTF _snprintf_s +#define TIXML_SSCANF sscanf_s +#elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) +// Microsoft visual studio, version 6 and higher. +//#pragma message( "Using _sn* functions." ) +#define TIXML_SNPRINTF _snprintf +#define TIXML_SSCANF sscanf +#elif defined(__GNUC__) && (__GNUC__ >= 3 ) +// GCC version 3 and higher.s +//#warning( "Using sn* functions." ) +#define TIXML_SNPRINTF snprintf +#define TIXML_SSCANF sscanf +#else +#define TIXML_SNPRINTF snprintf +#define TIXML_SSCANF sscanf +#endif +#endif class TiXmlDocument; class TiXmlElement; @@ -95,1708 +95,1708 @@ 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 - in the XML file. +/* Internal structure for tracking location of items + in the XML file. */ struct TiXmlCursor { - TiXmlCursor() { Clear(); } - void Clear() { row = col = -1; } + TiXmlCursor() { Clear(); } + void Clear() { row = col = -1; } - int row; // 0 based. - int col; // 0 based. + int row; // 0 based. + int col; // 0 based. }; /** - Implements the interface to the "Visitor pattern" (see the Accept() method.) - If you call the Accept() method, it requires being passed a TiXmlVisitor - class to handle callbacks. For nodes that contain other nodes (Document, Element) - you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves - are simply called with Visit(). + Implements the interface to the "Visitor pattern" (see the Accept() method.) + If you call the Accept() method, it requires being passed a TiXmlVisitor + class to handle callbacks. For nodes that contain other nodes (Document, Element) + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves + are simply called with Visit(). - 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. + 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 - visiting). You need to only override methods that are interesting to you. + 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. + Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. - You should never change the document from a callback. + You should never change the document from a callback. - @sa TiXmlNode::Accept() + @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; } + 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 -}; + { + TIXML_SUCCESS, + TIXML_NO_ATTRIBUTE, + TIXML_WRONG_TYPE + }; // Used by the parsing routines. enum TiXmlEncoding -{ - TIXML_ENCODING_UNKNOWN, - TIXML_ENCODING_UTF8, - TIXML_ENCODING_LEGACY -}; + { + TIXML_ENCODING_UNKNOWN, + TIXML_ENCODING_UTF8, + TIXML_ENCODING_LEGACY + }; const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; /** TiXmlBase is a base class for every class in TinyXml. - It does little except to establish that TinyXml classes - can be printed and provide some utility functions. - - In XML, the document and elements can contain - other elements and other types of nodes. - - @verbatim - A Document can contain: Element (container or leaf) - Comment (leaf) - Unknown (leaf) - Declaration( leaf ) - - An Element can contain: Element (container or leaf) - Text (leaf) - Attributes (not on tree) - Comment (leaf) - Unknown (leaf) - - A Decleration contains: Attributes (not on tree) - @endverbatim + It does little except to establish that TinyXml classes + can be printed and provide some utility functions. + + In XML, the document and elements can contain + other elements and other types of nodes. + + @verbatim + A Document can contain: Element (container or leaf) + Comment (leaf) + Unknown (leaf) + Declaration( leaf ) + + An Element can contain: Element (container or leaf) + Text (leaf) + Attributes (not on tree) + Comment (leaf) + Unknown (leaf) + + 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. - } - - #ifdef TIXML_USE_STL - 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; + 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 ); +#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; }; /** The parent class for everything in the Document Object Model. - (Except for attributes). - Nodes have siblings, a parent, and children. A node can be - 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. + (Except for attributes). + Nodes have siblings, a parent, and children. A node can be + 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 ); - - #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 (); } - - #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; } - #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;} - - #ifdef TIXML_USE_STL - /// 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 )); - } - - #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. - #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 ) ); - } - - #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. - #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. - - 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 ); - - /** 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 ); - - /** 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 ); - - /// 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 ) ); - } - - #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. - #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 ) ); - } - - #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. - #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 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. - #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; - - #ifdef TIXML_USE_STL - // 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 ); - - TiXmlNode* parent; - NodeType type; - - TiXmlNode* firstChild; - TiXmlNode* lastChild; - - TIXML_STRING value; - - TiXmlNode* prev; - TiXmlNode* next; - -private: - TiXmlNode( const TiXmlNode& ); // not implemented. - void operator=( const TiXmlNode& base ); // not allowed. + 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 (); } + +#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; } +#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;} + +#ifdef TIXML_USE_STL + /// 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 )); + } + +#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. +#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 ) ); + } + +#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. +#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. + + 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 ); + + /** 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 ); + + /** 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 ); + + /// 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 ) ); + } + +#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. +#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 ) ); + } + +#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. +#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 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. +#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; + +#ifdef TIXML_USE_STL + // 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 ); + + TiXmlNode* parent; + NodeType type; + + TiXmlNode* firstChild; + TiXmlNode* lastChild; + + TIXML_STRING value; + + TiXmlNode* prev; + TiXmlNode* next; + + private: + TiXmlNode( const TiXmlNode& ); // not implemented. + void operator=( const TiXmlNode& base ); // not allowed. }; /** An attribute is a name-value pair. Elements have an arbitrary - number of attributes, each with a unique name. + number of attributes, each with a unique name. - @note The attributes are not TiXmlNodes, since they are not - part of the tinyXML document object model. There are other - suggested ways to look at this problem. + @note The attributes are not TiXmlNodes, since they are not + 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; - } - - #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; - } - #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. - #ifdef TIXML_USE_STL - 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. - - #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; } - #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; + 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; + } +#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. +#ifdef TIXML_USE_STL + 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. + +#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; } +#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; }; -/* 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 - it a bit problematic and prevents the use of STL. +/* 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 + it a bit problematic and prevents the use of STL. - This version is implemented with circular lists because: - - I like circular lists - - it demonstrates some independence from the (typical) doubly linked list. + This version is implemented with circular lists because: + - I like circular lists + - it demonstrates some independence from the (typical) doubly linked list. */ class TiXmlAttributeSet { -public: - TiXmlAttributeSet(); - ~TiXmlAttributeSet(); + public: + TiXmlAttributeSet(); + ~TiXmlAttributeSet(); - void Add( TiXmlAttribute* attribute ); - void Remove( TiXmlAttribute* attribute ); + 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; } + 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 ); + 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 ); -# endif +# ifdef TIXML_USE_STL + 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; }; /** The element is a container class. It has a value, the element name, - and can contain other elements, text, comments, and unknowns. - Elements also contain an arbitrary number of attributes. + 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); - - #ifdef TIXML_USE_STL - /// 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; - } - - #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; - } - #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 ); - - #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 ); - #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 SetDoubleAttribute( const char * name, double value ); - - /** 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. - #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] - #ifdef TIXML_USE_STL - 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; + public: + /// Construct an element. + TiXmlElement (const char * in_value); + +#ifdef TIXML_USE_STL + /// 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; + } + +#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; + } +#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 ); + +#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 ); +#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 SetDoubleAttribute( const char * name, double value ); + + /** 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. +#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] +#ifdef TIXML_USE_STL + 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; }; -/** An XML comment. -*/ +/** 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 - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif -// virtual void StreamOut( TIXML_OSTREAM * out ) const; - -private: + 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 ); +#endif + // virtual void StreamOut( TIXML_OSTREAM * out ) const; + + private: }; /** 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 - SetCDATA() and query it with CDATA(). + 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 + 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() {} - - #ifdef TIXML_USE_STL - /// 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] - #ifdef TIXML_USE_STL - 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 + 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; + } +#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] +#ifdef TIXML_USE_STL + 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 }; /** In correct XML the declaration is the first entry in the file. - @verbatim - <?xml version="1.0" standalone="yes"?> - @endverbatim + @verbatim + <?xml version="1.0" standalone="yes"?> + @endverbatim - TinyXml will happily read or write files without a declaration, - however. There are 3 possible attributes to the declaration: - version, encoding, and standalone. + TinyXml will happily read or write files without a declaration, + however. There are 3 possible attributes to the declaration: + version, encoding, and standalone. - Note: In this version of the code, the attributes are - handled as special cases, not generic attributes, simply - because there can only be at most 3 and they are always the same. + Note: In this version of the code, the attributes are + 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 ) {} + 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 ); + /// Construct. + TiXmlDeclaration( const char* _version, + const char* _encoding, + const char* _standalone ); - TiXmlDeclaration( const TiXmlDeclaration& copy ); - TiXmlDeclaration& operator=( const TiXmlDeclaration& copy ); + TiXmlDeclaration( const TiXmlDeclaration& copy ); + TiXmlDeclaration& operator=( const TiXmlDeclaration& copy ); - virtual ~TiXmlDeclaration() {} + 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 (); } + /// 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 ); - } + /// 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 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. + 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; + /** 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 ); - #endif + protected: + void CopyTo( TiXmlDeclaration* target ) const; + // used to be public +#ifdef TIXML_USE_STL + 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; }; /** Any tag that tinyXml doesn't recognize is saved as an - unknown. It is a tag of text, but should not be modified. - It will be written back to the XML, unchanged, when the file - is saved. + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. - DTD tags get thrown into TiXmlUnknowns. + DTD tags get thrown into TiXmlUnknowns. */ class TiXmlUnknown : public TiXmlNode { -public: - TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} - virtual ~TiXmlUnknown() {} + 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; } + 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; + /// 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 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. + 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; + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; -protected: - void CopyTo( TiXmlUnknown* target ) const; + protected: + void CopyTo( TiXmlUnknown* target ) const; - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif +#ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); +#endif -private: + private: }; /** Always the top level node. A document binds together all the - XML pieces. It can be saved, loaded, and printed to the screen. - The 'value' of a document node is the xml file name. + 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 ); - - #ifdef TIXML_USE_STL - /// 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; - - #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() ); - } - #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; - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - -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. + 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 ); +#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; + +#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() ); + } +#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; +#ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); +#endif + + 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. }; /** - A TiXmlHandle is a class that wraps a node pointer with null checks; this is - an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml - DOM structure. It is a separate utility class. - - Take an example: - @verbatim - <Document> - <Element attributeA = "valueA"> - <Child attributeB = "value1" /> - <Child attributeB = "value2" /> - </Element> - <Document> - @endverbatim - - 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 - TiXmlElement* root = document.FirstChildElement( "Document" ); - if ( root ) - { - TiXmlElement* element = root->FirstChildElement( "Element" ); - if ( element ) - { - TiXmlElement* child = element->FirstChildElement( "Child" ); - if ( child ) - { - TiXmlElement* child2 = child->NextSiblingElement( "Child" ); - if ( child2 ) - { - // Finally do something useful. - @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 - and correct to use: - - @verbatim - TiXmlHandle docHandle( &document ); - TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); - if ( child2 ) - { - // do something useful - @endverbatim - - Which is MUCH more concise and useful. - - It is also safe to copy handles - internally they are nothing more than node pointers. - @verbatim - TiXmlHandle handleCopy = handle; - @endverbatim - - What they should not be used for is iteration: - - @verbatim - int i=0; - while ( true ) - { - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); - if ( !child ) - break; - // do something - ++i; - } - @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 - to. Instead, prefer: - - @verbatim - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); - - for( child; child; child=child->NextSiblingElement() ) - { - // do something - } - @endverbatim + A TiXmlHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + <Document> + <Element attributeA = "valueA"> + <Child attributeB = "value1" /> + <Child attributeB = "value2" /> + </Element> + <Document> + @endverbatim + + 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 + TiXmlElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + TiXmlElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + TiXmlElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + TiXmlElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @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 + and correct to use: + + @verbatim + TiXmlHandle docHandle( &document ); + TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + TiXmlHandle handleCopy = handle; + @endverbatim + + What they should not be used for is iteration: + + @verbatim + int i=0; + while ( true ) + { + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); + if ( !child ) + break; + // do something + ++i; + } + @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 + to. Instead, prefer: + + @verbatim + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); + + for( child; child; child=child->NextSiblingElement() ) + { + // do something + } + @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; - - #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 ); } - #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; + 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 ); } +#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; }; /** Print to memory functionality. The TiXmlPrinter is useful when you need to: - -# Print to memory (especially in non-STL mode) - -# Control formatting (line endings, etc.) + -# Print to memory (especially in non-STL mode) + -# Control formatting (line endings, etc.) - When constructed, the TiXmlPrinter is in its default "pretty printing" mode. - Before calling Accept() you can call methods to control the printing - of the XML document. After TiXmlNode::Accept() is called, the printed document can - be accessed via the CStr(), Str(), and Size() methods. + When constructed, the TiXmlPrinter is in its default "pretty printing" mode. + Before calling Accept() you can call methods to control the printing + of the XML document. After TiXmlNode::Accept() is called, the printed document can + be accessed via the CStr(), Str(), and Size() methods. - TiXmlPrinter uses the Visitor API. - @verbatim - TiXmlPrinter printer; - printer.SetIndent( "\t" ); + TiXmlPrinter uses the Visitor API. + @verbatim + TiXmlPrinter printer; + printer.SetIndent( "\t" ); - doc.Accept( &printer ); - fprintf( stdout, "%s", printer.CStr() ); - @endverbatim + doc.Accept( &printer ); + 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(); } - - #ifdef TIXML_USE_STL - /// 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; + 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; } +#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; }; diff --git a/tinyxml/tinyxmlerror.cpp b/tinyxml/tinyxmlerror.cpp index 538c21d0bd95fb114e70636bc1a776937975a912..ce96abfda5e138b1e54e7f11863cd05cfbc07e3c 100644 --- a/tinyxml/tinyxmlerror.cpp +++ b/tinyxml/tinyxmlerror.cpp @@ -33,20 +33,20 @@ distribution. 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.", + "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 a7e0137264ed4da6c19a6e75f34477c9761e8f3d..317300f77e9c9b28ba9c715748713bce70afef09 100644 --- a/tinyxml/tinyxmlparser.cpp +++ b/tinyxml/tinyxmlparser.cpp @@ -30,35 +30,35 @@ distribution. //#define DEBUG_PARSER #if defined( DEBUG_PARSER ) -# if defined( DEBUG ) && defined( _MSC_VER ) -# include <windows.h> -# define TIXML_LOG OutputDebugString -# else -# define TIXML_LOG printf -# endif +# if defined( DEBUG ) && defined( _MSC_VER ) +# include <windows.h> +# define TIXML_LOG OutputDebugString +# else +# define TIXML_LOG printf +# endif #endif // Note tha "PutString" hardcodes the same list. This // is less flexible than it appears. Changing the entries -// or order will break putstring. +// or order will break putstring. TiXmlBase::Entity TiXmlBase::entity[ TiXmlBase::NUM_ENTITY ] = { - { "&", 5, '&' }, - { "<", 4, '<' }, - { ">", 4, '>' }, - { """, 6, '\"' }, - { "'", 6, '\'' } + { "&", 5, '&' }, + { "<", 4, '<' }, + { ">", 4, '>' }, + { """, 6, '\"' }, + { "'", 6, '\'' } }; // Bunch of unicode info at: -// http://www.unicode.org/faq/utf_bom.html +// http://www.unicode.org/faq/utf_bom.html // 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: -// ef bb bf (Microsoft "lead bytes") -// ef bf be -// ef bf bf +// Beware of the non-characters in UTF-8: +// ef bb bf (Microsoft "lead bytes") +// ef bf be +// ef bf bf const unsigned char TIXML_UTF_LEAD_0 = 0xefU; const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; @@ -66,333 +66,333 @@ 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 + // 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; 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]); + } } /*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. - -// 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. -// } -// else -// { -// return isalpha( anyByte ); -// } + // 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. +// } +// else +// { +// return isalpha( anyByte ); +// } } /*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. - -// 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. -// } -// else -// { -// return isalnum( anyByte ); -// } + // 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. +// } +// else +// { +// return isalnum( anyByte ); +// } } class TiXmlParsingData { - friend class TiXmlDocument; + friend class TiXmlDocument; public: - void Stamp( const char* now, TiXmlEncoding encoding ); + void Stamp( const char* now, TiXmlEncoding encoding ); - const TiXmlCursor& Cursor() const { return cursor; } + 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; + // 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; ++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 ); } 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 +401,1239 @@ 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. + // 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; + 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; + 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; - } - } + 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; + 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(); + p = SkipWhiteSpace( p, encoding ); + TiXmlDocument* document = GetDocument(); - if ( !p || !*p ) - { - if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding ); - return 0; - } + 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 ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } - if ( *p != '<' ) - { - if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding ); - return 0; - } + if ( *p != '<' ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding ); + return 0; + } - p = SkipWhiteSpace( p+1, encoding ); + p = SkipWhiteSpace( p+1, encoding ); - // Read the name. - const char* pErr = p; + // 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; - } + 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; + 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; + 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; + 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> --> - */ + 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; + // 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; }