diff --git a/AUTHORS b/AUTHORS index 89b7a4a31851bfcb5b41d848316c07c589817540..a56f59a0bb21af285bf2aea5874d019b0040ed23 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,11 +1,23 @@ JuPedSim contributors: +(Date: 27.01.2016) Erik Andresen Mohcine Chraibi +Arne Graf David Haensel +Weichen Liao Ulrich Kemloh +Maximilian Osterkamp Andrea Portz Oliver Schmidts +Benjamin Schröder Denis Shhikhalev +Antoine Tordeux Jun Zhang +JPSeditor contributors: +(Date: 27.01.2016) + +Erik Andresen +Maximilian Osterkamp + diff --git a/CHANGELOG.md b/CHANGELOG.md index bab618f1ed2f377347083fde2c7184d8f285032a..e9318ad449da7d7f8233768a6cbea39635c2591f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,94 +6,18 @@ All notable changes to this project will be documented in this file. ### Added -#### JPSCORE -- CI with travis and Gitlab CI -- Compilation checked on Visual Studio 12 2013 -- Added more validation tests -- Added statistics (calculate exit usage) for all exits -- Added voronoi based algorithm for inserting agents coming from the source or from matsim -- New option for the quickest path router. Sample options are: - ```<parameters default_strategy="local_shortest">``` - ```<parameters default_strategy="global_shortest">``` - ``` <parameters cba_gain="0.15" reference_peds_selection="single" congestion_ratio="0.8" queue_vel_escaping_jam="0.2" - queue_vel_new_room="0.7" visibility_obstruction="4"> -``` -- New model with the generic name `Tordeux2015` and `id=3`. For use check the ini-files in the Utest-validation tests. -- Tests are sorted in `rimea_tests`, `juelich_tests` and `validation_tests`. -- Periodic boundary conditions with the option `<periodic>1</periodic>`.Works only with model 3. -- Added Floorfield to all exits, providing direction to target, direction to closest wall and cost estimates. Parameter to control wall-avoidance included. - -#### JPSVIS -- Added option to load vtk files. Need to add the line ``` <gradient_field filename="floorfield.vtk"> -``` in the header of the trajectory file. Alternatively drag and drop a vtk file on JPSvis. - -- Fixed error displaying the total number of frames when using the scroolbar - -#### JPSREPORT -- Added geometry information while plotting the voronoi cells -- Added option to disable plotting -- Issue a warning when the voronoi cell cannot be calculated -- Fixed error where all trajectories were colinear - #### JPSEDITOR - - -## v0.7.0 [2015-07-15] - -### New Module -- JuPedSim: Editor for the geometry - -### Added - -- Risk tolerance factor (value in [0 1]) for pedestrian. Pedestrians with high values are likely to take more risks. -- Added pre-movement time of the agents. Only after this time, the concerned agents will start moving. -- Sources for generating agents at runtime. Parameter are frequency (agents per seconds) and maximum number -- Option to color the pedestrians by group, spotlight, velocity, group, knowledge, router, final\_goal, intermediate\_goal. Usage: ( -```<trajectories format="xml-plain" fps="8" color_mode="group"> ```) -- More control over the triangulation specially to avoid skinny triangles. Usage: ```<navigation_mesh method="triangulation" minimum_distance_between_edges="0.5" minimum_angle_in_triangles="20" use_for_local_planning="true" />``` -- Improved statistics. The flow curve for the different exits can be computed at runtime. -- Changelog file -- Rimea testcases -- Unit tests are now based on the Boost testing engine -#### JPSVIS -- Display the geometry structure individual room/subroom. -- Now build on OSX/Linux/Windows - -### Changed -- -- - -### Fixed -- Visiblity in 3D -- Numerous geometrical operations - - -## v0.6.0 - 2015-01-31 -### Added -- Steering the simulation with predefined events (closing or opening doors during the simulation) -- Information sharing between the pedestrians. The agents now share their knowledge about closed doors. -- Pre evacuation time for groups of agents. -- Adjustable velocities on stairs and even terrain for group of agents. -- Stability and performance improvement. The simulation is approx 40% faster for larger scenarios and you will notice it -- New route choice model, cognitive map, giving agents the possibility to explore the environment and discover doors for instance. -- Different sensors for improving the navigation of pedestrians (smoke/jam sensor). -- New verification and validation tests. -- General statistics over the evacuation (for instance areas egress time and door usage) -- Support for Visual Studio and Xcode compilers. - - -### Changed -- refactor NumCPU and ExitCrossingStrategy tags to `num_threads and exit_crossing_strategy` - - - -## v0.5.0 - 2014-08-05 -First release of the the Juelich Pedestrian Simulator. Most noteworthy features: - -- Simulate pedestrians movement in a space continuous geometry -- Forces based models for describing the pedestrians interactions -- Shortest and quickest path route choice strategies -- Loading and visualizing trajectories and geometries -- Easy to use visualization interface -- Making high quality videos directly from the visualization interface or generating png sequences -- XML based input files \ No newline at end of file +- First approaches of an undo/redo framework + - Undo/Redo working when line added or deleted +- DXF import with different layers - Not working properly with AutoCAD ?! +- Bug fixes +- CAD features + - Point and line grid + - object snap + - Orthomode + - Zooming + - Line editing + - Length of line is displayed + - ... +- Room and door declarations + diff --git a/README.md b/README.md index 4c04dd71c00d29c39d5421737924460a76f1af37..c99fd77299f51a98334b86381e997d9323eae39d 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,33 @@ -JuPedSim v0.6 alpha +JuPedSim v0.8 alpha +JPSeditor v0.8 alpha ==================== -Ulrich Kemloh drafted this on 25 Jun 2014 +Erik Andresen drafted this on 27 Jun 2016 -We are proud to announce the first alpha release of our software JuPedSim for simulating pedestrians evacuations. Please note that it is a pre release version for developers only. We are working hard towards the final release for this version. Two modules are shipped with this pre-release: +We are proud to announce the first alpha release of our software JPSeditor (part of JuPedSim for simulating pedestrians evacuations). Please note that it is a pre release version for developers only. We are working hard towards the final release for this version. + +JPSeditor is a graphical user interface to create the geometry of a scenario simulated by JuPedSim. It comes with set of CAD- and further tools to simplify the creation of proper xml-files +incorporating information about the scenario' geometry. -- *jpscore*: command line simulation core -- *jpsvis*: visualization module Features ======== -- Simulate pedestrians movement in a space continuous geometry -- Forces-based models for describing the pedestrians interactions -- Shortest and quickest path route choice strategies -- Loading and visualizing trajectories and geometries -- Easy to use visualization interface -- Making high quality videos directly from the visualization interface or generating png screenshots -- XML based input files +- DXF Import / Export +- CAD features + - Point and line grid + - object snap + - Orthomode + - Zooming + - Line editing + - ... +- Tools for room and door declarations -Showcase +Tutorial ======== -To highlight some features of JuPedSim we have uploaded some videos on our [YouTube channel](https://www.youtube.com/user/JuPedSim). +To highlight some features of JuPedSim we have uploaded some videos on our [YouTube channel](https://www.youtube.com/user/JuPedSim) including a tutorial showing how to use the editor. Installing @@ -39,39 +43,7 @@ As JuPedSim comes with no installer, you just need to delete the unziped directo Running ======= - jpscore.exe my_simulation_ini.xml - -from the command line (or also dropping the file on the executable) will generate a trajectory file, which you can visualize with `jpsvis`. -You will find some projects samples in the downloaded files and further information in the manual. - -Compiling from sources -====================== - -You can compile the simulation core for your specific platform with the supplied cmake script. -The only requirement is a compiler supporting the new standard c++11. - -Windows (tested on Win7 with MinGW 4.8) ---------------------------------------- - - cmake -G "MinGW Makefiles" CMakeList.txt - make-mingw32.exe - -Linux (tested on Ubuntu 14.04 with gcc 4.8) ---------------- - - cmake CMakeList.txt - make - -OSX (tested on OSX Maverick with clang 5.1 and Yosemite with clang 6.1) ---------------------- - - cmake CMakeList.txt - make - -Note that the OpenMP acceleration might be missing under OSX - -For the visualization module (`jpsvis`) at least Qt version 4.5 and VTK version 4.8 are required. -You can download the latest version of QT [here](https://www.qt.io/download/) and the latest version of VTK [here](http://www.vtk.org/download/). +Start the application by clicking on the binary file. (For example .exe) System Requirements ============== @@ -79,11 +51,6 @@ System Requirements There is no special hardware/software requirements for running JuPedSim. The distributed binaries however, are only available for windows at the moment. For compiling from sources you need a compiler with c++11 support is needed for the core. Qt version >=4.5 and VTK >5.8 are needed for the visualization. -Known Issues -============ - -Some verification tests are still failing. The actual cdash-board can be found [here](http://my.cdash.org/index.php?project=JuPedSim) -Occasionaly jpscore crashes if the input file is not valid. Make sure to validate your XML input files with the supplied XSD files. Frequently Asked Questions =========================== diff --git a/forms/Ressource.qrc b/forms/Ressource.qrc index 647c8bb414eadc2c4408db1fd8363f0d7cd69cd6..ecefdd345d0269930e59a4597e6f09c1f559bcb8 100644 --- a/forms/Ressource.qrc +++ b/forms/Ressource.qrc @@ -40,5 +40,6 @@ <file>statue_specs.jpg</file> <file>anglesnap.PNG</file> <file>Undo-icon.png</file> + <file>Redo-Icon.png</file> </qresource> </RCC> diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index 6a1b77b5fa84d0693a542389b2e776e85ca8cf5d..97af0c19e3c334749a9002d6f3938eb69d99f4b1 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -101,9 +101,11 @@ <addaction name="actionSelect_Mode"/> <addaction name="separator"/> <addaction name="actionUndo"/> + <addaction name="actionRedo"/> <addaction name="separator"/> <addaction name="actionWall"/> <addaction name="actionDoor"/> + <addaction name="actionHLine"/> <addaction name="separator"/> <addaction name="actiongridmode"/> <addaction name="separator"/> @@ -526,6 +528,45 @@ <bool>true</bool> </property> </action> + <action name="actionRedo"> + <property name="icon"> + <iconset resource="Ressource.qrc"> + <normaloff>:/Redo-Icon.png</normaloff>:/Redo-Icon.png</iconset> + </property> + <property name="text"> + <string>Redo</string> + </property> + <property name="toolTip"> + <string>Redo</string> + </property> + <property name="shortcut"> + <string>Ctrl+U</string> + </property> + </action> + <action name="actionHLine"> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="icon"> + <iconset resource="Ressource.qrc"> + <normaloff>:/Wall.png</normaloff>:/Wall.png</iconset> + </property> + <property name="text"> + <string>HLine</string> + </property> + <property name="toolTip"> + <string>HLine</string> + </property> + <property name="shortcut"> + <string>H</string> + </property> + <property name="iconVisibleInMenu"> + <bool>true</bool> + </property> + </action> </widget> <resources> <include location="Ressource.qrc"/> diff --git a/jpseditor.pro b/jpseditor.pro index 9562618608d3d62bf208c28cc970ae94117e6695..7186b31fc7d00e9c9b258e45714fb0c87b6dbdcf 100644 --- a/jpseditor.pro +++ b/jpseditor.pro @@ -59,8 +59,8 @@ HEADERS += \ src/jpsyahpointer.h \ src/jpsconnection.h \ src/UndoFramework/actionstack.h \ - src/UndoFramework/paintaction.h \ - src/UndoFramework/action.h + src/UndoFramework/action.h \ + src/UndoFramework/lineaction.h SOURCES += \ @@ -84,8 +84,8 @@ SOURCES += \ src/jpsyahpointer.cpp \ src/jpsconnection.cpp \ src/UndoFramework/actionstack.cpp \ - src/UndoFramework/paintaction.cpp \ - src/UndoFramework/action.cpp + src/UndoFramework/action.cpp \ + src/UndoFramework/lineaction.cpp RESOURCES += forms/Ressource.qrc diff --git a/src/GraphicView.cpp b/src/GraphicView.cpp index 2f8e26b2e345a038263ef611fa605175cd54fb77..1bbc9fba4c7090123697534fd2673ceae3564179 100644 --- a/src/GraphicView.cpp +++ b/src/GraphicView.cpp @@ -64,6 +64,7 @@ jpsGraphicsView::jpsGraphicsView(QWidget* parent):QGraphicsView(parent) statWall=false; statDoor=false; statExit=false; + _statHLine=false; statLandmark=false; markedLandmark=nullptr; currentLandmarkRect=nullptr; @@ -206,9 +207,9 @@ void jpsGraphicsView::mousePressEvent(QMouseEvent *mouseEvent) if (mouseEvent->button() == Qt::LeftButton) { - if (statWall==true || statDoor==true || statExit==true) + if (statWall || statDoor || statExit || _statHLine) { - /// If line is edited currently + // If line is edited currently if (_statLineEdit) { for (jpsLineItem* line:line_vector) @@ -774,11 +775,11 @@ void jpsGraphicsView::catch_lines() void jpsGraphicsView::drawLine() { - if (current_line==nullptr) /// if the mouse was pressed first of two times + if (current_line==nullptr) // if the mouse was pressed first of two times { - ///Determining first point of line + //Determining first point of line - /// all two points of the line are inited with the cursorcoordinates + // all two points of the line are inited with the cursorcoordinates current_line = Scene->addLine(translated_pos.x(),translated_pos.y(),translated_pos.x(),translated_pos.y(),currentPen); //current_line->translate(translation_x,translation_y); current_line->setTransform(QTransform::fromTranslate(translation_x,translation_y), true); @@ -804,19 +805,22 @@ void jpsGraphicsView::drawLine() } } - lineItem->set_type(statWall,statDoor,statExit); + lineItem->set_type(statWall,statDoor,statExit,_statHLine); line_vector.push_back(lineItem); - ///reset pointer + //reset pointer current_line=nullptr; + //Undo + RecordUndoLineAction("LineAdded",lineItem->GetType(),lineItem->get_line()->line()); + drawLine(); } - ///Vline + //Vline if (_currentVLine!=nullptr) { delete _currentVLine; @@ -849,16 +853,16 @@ void jpsGraphicsView::disable_drawing() statExit=false; statLandmark=false; _statLineEdit=false; - /// if drawing was canceled by pushing ESC + // if drawing was canceled by pushing ESC if (current_line!=nullptr) { - ///not completed line will be deleted + //not completed line will be deleted delete current_line; current_line=nullptr; } if (_currentVLine!=nullptr) { - ///VLine will be deleted + //VLine will be deleted delete _currentVLine; _currentVLine=nullptr; } @@ -910,6 +914,11 @@ jpsLineItem* jpsGraphicsView::addLineItem(const qreal &x1,const qreal &y1,const } +jpsLineItem *jpsGraphicsView::addLineItem(const QLineF &line, const QString &type) +{ + return addLineItem(line.p1().x(),line.p1().y(),line.p2().x(),line.p2().y(),type); +} + void jpsGraphicsView::locate_intersection(jpsLineItem *item1, jpsLineItem *item2) { @@ -1039,26 +1048,65 @@ bool jpsGraphicsView::show_hide_roomCaption(QString name, qreal x, qreal y) return true; } -//void jpsGraphicsView::RecordLineAction(const QString& name, const QString& type, const QLineF &oldLine) -//{ -// _undoStack.PushNewAction(LineAction(name,type,oldLine)); -//} +void jpsGraphicsView::RecordUndoLineAction(const QString& name, const QString& type, const QLineF &oldLine) +{ + _undoStack.PushNewAction(LineAction(name,type,oldLine)); +} + +void jpsGraphicsView::RecordRedoLineAction(const QString &name, const QString &type, const QLineF &oldLine) +{ + _redoStack.PushNewAction(LineAction(name,type,oldLine)); +} + +void jpsGraphicsView::Undo() +{ + if (!_undoStack.IsEmpty()) + { + const LineAction recentAction = _undoStack.GetRecentAction(); + + if (recentAction.GetName()=="LineDeleted") + { + addLineItem(recentAction.GetOldLine().p1().x(),recentAction.GetOldLine().p1().y(),recentAction.GetOldLine().p2().x(), + recentAction.GetOldLine().p2().y(),recentAction.GetType()); + + RecordRedoLineAction("LineAdded",recentAction.GetType(),QLineF(0,0,0,0)); + } + else if (recentAction.GetName()=="LineAdded") + { + RecordRedoLineAction("LineDeleted",line_vector.back()->GetType(),line_vector.back()->get_line()->line()); + RemoveLineItem(line_vector.back()); + } + } + +} + +void jpsGraphicsView::Redo() +{ + if (!_redoStack.IsEmpty()) + { + const LineAction recentAction = _redoStack.GetRecentAction(); + + if (recentAction.GetName()=="LineDeleted") + { + addLineItem(recentAction.GetOldLine().p1().x(),recentAction.GetOldLine().p1().y(),recentAction.GetOldLine().p2().x(), + recentAction.GetOldLine().p2().y(),recentAction.GetType()); -//void jpsGraphicsView::Undo() -//{ -// const LineAction recentAction = _undoStack.GetRecentAction(); + RecordUndoLineAction("LineAdded",recentAction.GetType(),QLineF(0,0,0,0)); + } + else if (recentAction.GetName()=="LineAdded") + { + RecordUndoLineAction("LineDeleted",line_vector.back()->GetType(),line_vector.back()->get_line()->line()); + RemoveLineItem(line_vector.back()); -// if (recentAction.GetName()=="LineDeleted") -// addLineItem(recentAction.GetOldLine().p1().x(),recentAction.GetOldLine().p1().y(),recentAction.GetOldLine().p2().x(), -// recentAction.GetOldLine().p2().y(),recentAction.GetType()); + } -// _redoStack.PushNewAction(LineAction("LineAdded",recentAction.GetType(),QLineF(0,0,0,0))); -//} + } +} -void jpsGraphicsView::line_collision() ///FIX ME!!! +void jpsGraphicsView::line_collision() //FIX ME!!! { /// if no lines collided yet if (!lines_collided && current_line!=nullptr) @@ -1395,22 +1443,20 @@ void jpsGraphicsView::delete_marked_lines() for (int i=0; i<marked_lines.size(); ++i) { + RecordUndoLineAction("LineDeleted",marked_lines[i]->GetType(),marked_lines[i]->get_line()->line()); RemoveIntersections(marked_lines[i]); + delete marked_lines[i]->get_line(); //marked_lines[i]->set_line(nullptr); delete marked_lines[i]; line_vector.removeOne(marked_lines[i]); + } - QString type; - if (marked_lines.back()->is_Door()) - type = "Door"; - else - type = "Wall"; - //RecordLineAction("LineDeleted",type,marked_lines.back()->get_line()->line()); + marked_lines.clear(); //intersect_point_vector.clear(); @@ -1421,6 +1467,30 @@ void jpsGraphicsView::delete_marked_lines() } +void jpsGraphicsView::RemoveLineItem(jpsLineItem *mline) +{ + RemoveIntersections(mline); + line_vector.removeOne(mline); + delete mline->get_line(); + delete mline; + emit lines_deleted(); + +} + +void jpsGraphicsView::RemoveLineItem(const QLineF &line) +{ + for (jpsLineItem* lineItem:line_vector) + { + if (lineItem->get_line()->line()==line) + { + unmark_all_lines(); + select_line(lineItem); + delete_marked_lines(); + } + } + +} + void jpsGraphicsView::RemoveIntersections(jpsLineItem *lineItem) { QList<QPointF *> points = lineItem->get_intersectionVector(); @@ -1565,6 +1635,7 @@ void jpsGraphicsView::en_disableWall() statWall=!statWall; statDoor=false; statExit=false; + _statHLine=false; statLandmark=false; if (statWall==false) { @@ -1598,6 +1669,7 @@ void jpsGraphicsView::en_disableDoor() statExit=false; statWall=false; statLandmark=false; + _statHLine=false; if (statDoor==false) { emit no_drawing(); @@ -1619,6 +1691,7 @@ void jpsGraphicsView::en_disableExit() statExit=!statExit; statDoor=false; statWall=false; + _statHLine=false; statLandmark=false; if (statExit==false) { @@ -1630,6 +1703,28 @@ void jpsGraphicsView::en_disableExit() } } +bool jpsGraphicsView::statusHLine() +{ + return _statHLine; +} + +void jpsGraphicsView::en_disableHLine() +{ + _statHLine=!_statHLine; + statExit=false; + statDoor=false; + statWall=false; + statLandmark=false; + if (_statHLine==false) + { + emit no_drawing(); + } + else + { + currentPen.setColor(Qt::darkCyan); + } +} + bool jpsGraphicsView::statusLandmark() { return statLandmark; diff --git a/src/GraphicView.h b/src/GraphicView.h index 5f8d6befc7df42cd02e813deb14f482d2f64c3cc..06be9be84f013b9d71818a36c5ea1ee815e34c11 100644 --- a/src/GraphicView.h +++ b/src/GraphicView.h @@ -63,6 +63,8 @@ public: void en_disableDoor(); bool statusExit(); void en_disableExit(); + bool statusHLine(); + void en_disableHLine(); bool statusLandmark(); void en_disableLandmark(); @@ -96,9 +98,12 @@ public: void drawLine(); qreal calc_d_point(const QLineF &line, const qreal &x, const qreal &y); void delete_marked_lines(); + void RemoveLineItem(jpsLineItem *mline); + void RemoveLineItem(const QLineF &line); void RemoveIntersections(jpsLineItem* lineItem); // lines read from dxf-file jpsLineItem *addLineItem(const qreal &x1, const qreal &y1, const qreal &x2, const qreal &y2, const QString &type=""); + jpsLineItem *addLineItem(const QLineF &line, const QString &type=""); QList<jpsLineItem *> get_markedLines(); QList<jpsLineItem *> get_line_vector(); void unmark_all_lines(); @@ -127,8 +132,8 @@ public: bool show_hide_roomCaption(QString name, qreal x, qreal y); //Undo Framework - //void RecordLineAction(const QString &name, const QString &type, const QLineF &oldLine); - + void RecordUndoLineAction(const QString &name, const QString &type, const QLineF &oldLine); + void RecordRedoLineAction(const QString &name, const QString &type, const QLineF &oldLine); public slots: //Waypoints @@ -142,7 +147,8 @@ public slots: //Line operations void SelectAllLines(); //Undo Redo - //void Undo(); + void Undo(); + void Redo(); protected: //Mouse events @@ -155,6 +161,7 @@ protected: private: QGraphicsLineItem* current_line; + QPolygonF polygon; //std::vector<jpsLineItem> line_vector; QList<QPointF *> intersect_point_vector; //QList<QPointF> grid_point_vector; @@ -174,6 +181,7 @@ private: bool statDoor; bool statExit; bool statLandmark; + bool _statHLine; qreal catch_radius; qreal _scaleFactor; qreal gl_scale_f; @@ -208,8 +216,8 @@ private: bool _gridmode; //Undo/Redo - //ActionStack _undoStack; - //ActionStack _redoStack; + ActionStack _undoStack; + ActionStack _redoStack; signals: diff --git a/src/UndoFramework/actionstack.cpp b/src/UndoFramework/actionstack.cpp index 420c9c11111ad96d47398f021ce1cc9260a28703..84bf454ecd7b7bbc29aff7f8f815ff91ce5128b6 100644 --- a/src/UndoFramework/actionstack.cpp +++ b/src/UndoFramework/actionstack.cpp @@ -11,7 +11,7 @@ ActionStack::~ActionStack() } LineAction ActionStack::GetRecentAction() -{ +{ return _actionstack.pop(); } @@ -21,3 +21,8 @@ void ActionStack::PushNewAction(const LineAction &action) } +bool ActionStack::IsEmpty() +{ + return _actionstack.isEmpty(); +} + diff --git a/src/UndoFramework/actionstack.h b/src/UndoFramework/actionstack.h index 3a677f16e724d4ffb8c5a90b5f5f4f1e51c3f38e..364f7f54a387b69922347766693d9fc435cba5ca 100644 --- a/src/UndoFramework/actionstack.h +++ b/src/UndoFramework/actionstack.h @@ -3,7 +3,7 @@ #include <QStack> #include "action.h" -#include "paintaction.h" +#include "lineaction.h" class ActionStack { @@ -13,6 +13,7 @@ public: LineAction GetRecentAction(); void PushNewAction(const LineAction& action); + bool IsEmpty(); private: QStack<LineAction> _actionstack; }; diff --git a/src/UndoFramework/paintaction.cpp b/src/UndoFramework/paintaction.cpp deleted file mode 100644 index d40877c100fb838972d2f2dc610e298e6afd13fe..0000000000000000000000000000000000000000 --- a/src/UndoFramework/paintaction.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "paintaction.h" - -LineAction::LineAction() -{ - -} - -LineAction::LineAction(const QString &name, const QString &type, const QLineF &oldLine) : Action(name,type) -{ - _oldLine=oldLine; -} - -LineAction::~LineAction() -{ - -} - -QLineF LineAction::GetOldLine() const -{ - return _oldLine; -} - diff --git a/src/UndoFramework/paintaction.h b/src/UndoFramework/paintaction.h deleted file mode 100644 index d87f0a3085ec8d7cc9eff4ab72059ec32ee20428..0000000000000000000000000000000000000000 --- a/src/UndoFramework/paintaction.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef PAINTACTION_H -#define PAINTACTION_H - -#include "action.h" -#include <QLine> - -class LineAction : public Action -{ -public: - LineAction(); - LineAction(const QString& name, const QString& type, const QLineF& oldLine); - ~LineAction(); - - QLineF GetOldLine() const; -private: - QLineF _oldLine; -}; - -#endif // PAINTACTION_H diff --git a/src/datamanager.cpp b/src/datamanager.cpp index 117bb25614d98c3443b4468b5ce14111f6e11082..da93a7b42615e4317576099e0745d1b06c1e8191 100644 --- a/src/datamanager.cpp +++ b/src/datamanager.cpp @@ -277,6 +277,32 @@ void jpsDatamanager::writeXML(QFile &file) delete stream; } +void jpsDatamanager::writeRoutingXML(QFile &file) // Construction side +{ + QXmlStreamWriter* stream = new QXmlStreamWriter(&file); + QList<jpsLineItem* > hLines; + + for (jpsLineItem* line:mView->get_line_vector()) + { + if (line->IsHLine()) + { + hLines.push_back(line); + } + } + + + writeRoutingHeader(stream); + + stream->writeStartElement("Hlines"); + writeHLines(stream,hLines); + stream->writeEndElement();//Hlines + + stream->writeEndDocument(); + + delete stream; + +} + void jpsDatamanager::AutoSaveXML(QFile &file) { QXmlStreamWriter* stream = new QXmlStreamWriter(&file); @@ -310,13 +336,87 @@ void jpsDatamanager::writeHeader(QXmlStreamWriter *stream) stream->writeStartDocument("1.0",true); stream->writeStartElement("geometry"); - stream->writeAttribute("version", "0.5"); + stream->writeAttribute("version", "0.8"); stream->writeAttribute("caption","corner"); stream->writeAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance"); stream->writeAttribute("xsi:noNamespaceSchemaLocation","http://xsd.jupedsim.org/jps_geometry.xsd"); stream->writeAttribute("unit","m"); } +void jpsDatamanager::writeRoutingHeader(QXmlStreamWriter *stream) +{ + stream->setAutoFormatting(true); + stream->writeStartDocument("1.0",true); + + stream->writeStartElement("routing"); + stream->writeAttribute("version", "0.8"); + //stream->writeAttribute("caption","corner"); + stream->writeAttribute("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance"); + stream->writeAttribute("xsi:noNamespaceSchemaLocation","http://xsd.jupedsim.org/jps_routing.xsd"); + stream->writeAttribute("unit","m"); +} + +void jpsDatamanager::writeHLines(QXmlStreamWriter *stream, QList<jpsLineItem *> &hLines) +{ + for (jpsLineItem *lineItem:hLines) + { + stream->writeStartElement("Hline"); + stream->writeAttribute("room_id","0"); + QString rid = RoomIDHLine(lineItem); + if (rid.contains("Warning")) + { + QMessageBox::critical(mView, + "WriteHLines", + rid, + QMessageBox::Ok); + } + stream->writeAttribute("subroom_id",rid); + + //Vertices + stream->writeStartElement("vertex"); + stream->writeAttribute("px",QString::number(lineItem->get_line()->line().p1().x())); + stream->writeAttribute("py",QString::number(lineItem->get_line()->line().p1().y())); + stream->writeEndElement(); //vertex + + stream->writeStartElement("vertex"); + stream->writeAttribute("px",QString::number(lineItem->get_line()->line().p2().x())); + stream->writeAttribute("py",QString::number(lineItem->get_line()->line().p2().y())); + stream->writeEndElement(); //vertex + + stream->writeEndElement(); //Hline + } +} + +QString jpsDatamanager::RoomIDHLine(jpsLineItem *lineItem) +{ + + for (jpsRoom* room:roomlist) + { + QPolygonF rPolygon = room->RoomAsPolygon(); + if (rPolygon.containsPoint(lineItem->get_line()->line().p1(),Qt::OddEvenFill) || + rPolygon.contains(lineItem->get_line()->line().p1())) + { + if (rPolygon.containsPoint(lineItem->get_line()->line().p2(),Qt::OddEvenFill)|| + rPolygon.contains(lineItem->get_line()->line().p2())) + return QString::number(room->get_id()); + else + return "Warning! HLine intersects walls"; + } + else if (rPolygon.containsPoint(lineItem->get_line()->line().p2(),Qt::OddEvenFill)|| + rPolygon.contains(lineItem->get_line()->line().p2())) + { + if (rPolygon.containsPoint(lineItem->get_line()->line().p1(),Qt::OddEvenFill)|| + rPolygon.contains(lineItem->get_line()->line().p1())) + return QString::number(room->get_id()); + else + return "Warning! HLine intersects walls"; + } + + } + return "Warning! HLine outside geometry"; + +} + void jpsDatamanager::writeRooms(QXmlStreamWriter *stream, QList<jpsLineItem *> &lines) { ///rooms @@ -365,7 +465,7 @@ void jpsDatamanager::writeRooms(QXmlStreamWriter *stream, QList<jpsLineItem *> & } - ///Crossings + //Crossings writeCrossings(stream,lines); stream->writeEndElement();//crossings @@ -756,29 +856,29 @@ jpsGraphicsView * jpsDatamanager::get_view() return mView; } -void jpsDatamanager::AutoAssignCrossings() -{ - QList<jpsCrossing* > crossings = crossingList; +//void jpsDatamanager::AutoAssignCrossings() +//{ +// QList<jpsCrossing* > crossings = crossingList; - for (jpsCrossing *crossing: crossings) - { - int roomCounter=0; - for (jpsRoom *room : roomlist) - { - if (room->ContainsDoor(crossing->get_cLine()) && roomCounter==0) - { - crossing->add_rooms(room); - roomCounter++; +// for (jpsCrossing *crossing: crossings) +// { +// int roomCounter=0; +// for (jpsRoom *room : roomlist) +// { +// if (room->ContainsDoor(crossing->get_cLine()) && roomCounter==0) +// { +// crossing->add_rooms(room); +// roomCounter++; - } - else if (room->ContainsDoor(crossing->get_cLine()) && roomCounter==1) - { - crossing->add_rooms(crossing->get_roomList()[0],room); - crossings.removeOne(crossing); - break; - } - } - } +// } +// else if (room->ContainsDoor(crossing->get_cLine()) && roomCounter==1) +// { +// crossing->add_rooms(crossing->get_roomList()[0],room); +// crossings.removeOne(crossing); +// break; +// } +// } +// } @@ -822,38 +922,38 @@ void jpsDatamanager::AutoAssignCrossings() -} +//} -void jpsDatamanager::AutoAssignExits() -{ - for (jpsExit *exit: exitList) - { - for (jpsRoom *room: roomlist) - { - QList<jpsLineItem* > walls = room->get_listWalls(); +//void jpsDatamanager::AutoAssignExits() +//{ +// for (jpsExit *exit: exitList) +// { +// for (jpsRoom *room: roomlist) +// { +// QList<jpsLineItem* > walls = room->get_listWalls(); - int pointCounter = 0; +// int pointCounter = 0; - for (jpsLineItem* wall: walls) - { - if (wall->get_line()->line().p1()==exit->get_cLine()->get_line()->line().p1() || - wall->get_line()->line().p1()==exit->get_cLine()->get_line()->line().p2() || - wall->get_line()->line().p2()==exit->get_cLine()->get_line()->line().p1() || - wall->get_line()->line().p2()==exit->get_cLine()->get_line()->line().p2()) - { - pointCounter++; - } - } +// for (jpsLineItem* wall: walls) +// { +// if (wall->get_line()->line().p1()==exit->get_cLine()->get_line()->line().p1() || +// wall->get_line()->line().p1()==exit->get_cLine()->get_line()->line().p2() || +// wall->get_line()->line().p2()==exit->get_cLine()->get_line()->line().p1() || +// wall->get_line()->line().p2()==exit->get_cLine()->get_line()->line().p2()) +// { +// pointCounter++; +// } +// } - if (pointCounter==2) - { - exit->add_rooms(room); - break; - } - } - } +// if (pointCounter==2) +// { +// exit->add_rooms(room); +// break; +// } +// } +// } -} +//} bool jpsDatamanager::readXML(QFile &file) { diff --git a/src/datamanager.h b/src/datamanager.h index cf9a036a8e30beb63e96ede95977ed71f4ec9537..fd35fa6ce5f9be1b4548597ad7166b494ab3f0de 100644 --- a/src/datamanager.h +++ b/src/datamanager.h @@ -97,8 +97,8 @@ public: // Auto Assign - void AutoAssignCrossings(); - void AutoAssignExits(); +// void AutoAssignCrossings(); +// void AutoAssignExits(); // Read XML @@ -112,8 +112,12 @@ public: // Write XML void writeXML(QFile &file); + void writeRoutingXML(QFile &file); void AutoSaveXML(QFile &file); void writeHeader(QXmlStreamWriter *stream); + void writeRoutingHeader(QXmlStreamWriter *stream); + void writeHLines(QXmlStreamWriter *stream, QList<jpsLineItem* >& hLines); + QString RoomIDHLine(jpsLineItem* lineItem); void writeRooms(QXmlStreamWriter *stream, QList<jpsLineItem* >& lines); void AutoSaveRooms(QXmlStreamWriter *stream, QList<jpsLineItem* >& lines); void writeCrossings(QXmlStreamWriter *stream, QList<jpsLineItem* >& lines); diff --git a/src/jpsLineItem.cpp b/src/jpsLineItem.cpp index 20896675e0804e811b2a277ceda7002bd4f104cb..10301c4c61e13948777e2414b343e857512581e9 100644 --- a/src/jpsLineItem.cpp +++ b/src/jpsLineItem.cpp @@ -58,6 +58,16 @@ QString jpsLineItem::get_name() return mName; } +QString jpsLineItem::GetType() +{ + if (is_Door()) + return "Door"; + else if (is_Wall()) + return "Wall"; + else if (IsHLine()) + return "HLine"; +} + void jpsLineItem::set_id(int id) { mId=id; @@ -68,7 +78,7 @@ void jpsLineItem::set_name(QString name) mName=name; } -void jpsLineItem::set_type(bool wall, bool door, bool exit) +void jpsLineItem::set_type(bool wall, bool door, bool exit, bool hline) { if (wall==true) { @@ -82,6 +92,8 @@ void jpsLineItem::set_type(bool wall, bool door, bool exit) { set_Exit(); } + else + SetHLine(); } void jpsLineItem::set_Wall() @@ -89,6 +101,7 @@ void jpsLineItem::set_Wall() wall=true; door=false; exit=false; + _hLine=false; defaultColor="black"; } @@ -97,6 +110,7 @@ void jpsLineItem::set_Door() door=true; wall=false; exit=false; + _hLine=false; defaultColor="blue"; } @@ -105,10 +119,21 @@ void jpsLineItem::set_Exit() exit=true; wall=false; door=false; + _hLine=false; defaultColor="darkMagenta"; } +void jpsLineItem::SetHLine() +{ + exit=false; + wall=false; + door=false; + _hLine=true; + defaultColor="darkCyan"; + +} + void jpsLineItem::set_defaultColor(QString color) { defaultColor=color; @@ -129,6 +154,11 @@ bool jpsLineItem::is_Exit() return exit; } +bool jpsLineItem::IsHLine() +{ + return _hLine; +} + void jpsLineItem::add_intersectionPoint(QPointF *point) { intersectionVector.push_back(point); diff --git a/src/jpsLineItem.h b/src/jpsLineItem.h index d381b6169ea5d21cf89b51665032d4d9b9c15044..3ebb525d7841de23f98c52f2d54836b78721e623 100644 --- a/src/jpsLineItem.h +++ b/src/jpsLineItem.h @@ -42,16 +42,19 @@ public: int get_id(); QString get_defaultColor(); QString get_name(); + QString GetType(); void set_id(int id); void set_name(QString name); - void set_type(bool wall, bool door, bool exit); + void set_type(bool wall, bool door, bool exit, bool hline=false); void set_Wall(); void set_Door(); void set_Exit(); + void SetHLine(); void set_defaultColor(QString color); bool is_Wall(); bool is_Door(); bool is_Exit(); + bool IsHLine(); void add_intersectionPoint(QPointF *point); void remove_intersectionPoint(QPointF *point); QList<QPointF *> get_intersectionVector(); @@ -70,6 +73,7 @@ private: bool wall; bool door; bool exit; + bool _hLine; QList<QPointF *> intersectionVector; QList<jpsLineItem* > intersectLineVector; /* diff --git a/src/jpscrossing.cpp b/src/jpscrossing.cpp index 9fb51983e728867d85e79944c032aadf2456934d..a5f7e9a7a3278b54092e4a86786249c86fc30084 100644 --- a/src/jpscrossing.cpp +++ b/src/jpscrossing.cpp @@ -70,9 +70,11 @@ void jpsCrossing::add_rooms(jpsRoom *room1, jpsRoom *room2) { roomList.clear(); roomList.push_back(room1); + room1->AddDoor(this); if (room2!=0L) { roomList.push_back(room2); + room2->AddDoor(this); } diff --git a/src/mainWindow.cpp b/src/mainWindow.cpp index 7b1d5256e8362669240e9891cf521b419b1d3645..153e93f246303d773c28b1394ff20c1ff2dca1ed 100644 --- a/src/mainWindow.cpp +++ b/src/mainWindow.cpp @@ -106,6 +106,7 @@ MWindow :: MWindow() { connect(actionWall,SIGNAL(triggered(bool)),this,SLOT(en_disableWall())); connect(actionDoor,SIGNAL(triggered(bool)),this,SLOT(en_disableDoor())); connect(actionExit,SIGNAL(triggered(bool)),this,SLOT(en_disableExit())); + connect(actionHLine,SIGNAL(triggered(bool)),this,SLOT(en_disableHLine())); connect(actionObjectsnap,SIGNAL(triggered(bool)),this,SLOT(objectsnap())); connect(actionDelete_lines,SIGNAL(triggered(bool)),this,SLOT(delete_lines())); connect(actionDelete_single_line,SIGNAL(triggered(bool)),this,SLOT(delete_marked_lines())); @@ -143,8 +144,9 @@ MWindow :: MWindow() { //CMap connect(actionRun_visualisation,SIGNAL(triggered(bool)),this,SLOT(RunCMap())); connect(_cMapTimer,SIGNAL(timeout()),this,SLOT(UpdateCMap())); - //Undo - //connect(actionUndo,SIGNAL(triggered(bool)),mview,SLOT(Undo())); + //Undo Redo + connect(actionUndo,SIGNAL(triggered(bool)),mview,SLOT(Undo())); + connect(actionRedo,SIGNAL(triggered(bool)),mview,SLOT(Redo())); } MWindow::~MWindow() @@ -335,6 +337,13 @@ void MWindow::saveFile(){ return; } dmanager->writeXML(file); + + //routing (hlines) + QString fileNameRouting = fileName+"routing.xml"; + QFile routingFile(fileNameRouting); + if (routingFile.open(QIODevice::WriteOnly|QIODevice::Text)) + dmanager->writeRoutingXML(routingFile); + //file.write(coord_string.toUtf8());//textEdit->toPlainText().toUtf8()); statusBar()->showMessage(tr("XML-File successfully saved!"),10000); } @@ -399,12 +408,20 @@ void MWindow::en_disableLandmark() mview->en_disableLandmark(); } +void MWindow::en_disableHLine() +{ + this->disableDrawing(); + actionHLine->setChecked(true); + mview->en_disableHLine(); +} + void MWindow::disableDrawing() { this->actionWall->setChecked(false); this->actionDoor->setChecked(false); this->actionExit->setChecked(false); this->actionLandmark->setChecked(false); + this->actionHLine->setChecked(false); } void MWindow::objectsnap() @@ -517,6 +534,7 @@ void MWindow::remove_all_lines() void MWindow::ShowLineLength() { length_edit->setText(QString::number(mview->ReturnLineLength())); + length_edit->selectAll(); } void MWindow::rotate() diff --git a/src/mainWindow.h b/src/mainWindow.h index cec949375709674ef0240b839dac982395a8f0ed..75e99c3cb7251d480db65446c970d74d3e65877b 100644 --- a/src/mainWindow.h +++ b/src/mainWindow.h @@ -88,6 +88,7 @@ protected slots: void en_disableDoor(); void en_disableExit(); void en_disableLandmark(); + void en_disableHLine(); void disableDrawing(); void objectsnap(); diff --git a/src/rooms.cpp b/src/rooms.cpp index f58763c60b3afa2ce8a1f655ff2189515bcb2aa2..19f533f2f449cb532368c18c41072d1b4e037337 100644 --- a/src/rooms.cpp +++ b/src/rooms.cpp @@ -30,6 +30,7 @@ #include <QtGui> #include <iostream> #include <QGraphicsLineItem> +#include "jpscrossing.h" jpsRoom::jpsRoom(int id_room) @@ -88,9 +89,9 @@ void jpsRoom::activate() } } -QList<QPointF> jpsRoom::get_vertices() +QVector<QPointF> jpsRoom::get_vertices() const { - QList<QPointF> vertices; + QVector<QPointF> vertices; for (int i=0; i<item_list.size(); i++) { @@ -103,13 +104,26 @@ QList<QPointF> jpsRoom::get_vertices() vertices.push_back(item_list[i]->get_line()->line().p2()); } } + for (jpsCrossing* crossing:_doorList) + { + if (vertices.contains(crossing->get_cLine()->get_line()->line().p1())==false) + { + vertices.push_back(crossing->get_cLine()->get_line()->line().p1()); + } + + if (vertices.contains(crossing->get_cLine()->get_line()->line().p1())==false) + { + vertices.push_back(crossing->get_cLine()->get_line()->line().p1()); + } + + } return vertices; } QPointF jpsRoom::get_center() { - QList<QPointF> vertices = get_vertices(); + QVector<QPointF> vertices = get_vertices(); qreal sum_x=0; qreal sum_y=0; @@ -198,21 +212,31 @@ QList<QPointF> jpsRoom::GetDoorVertices() const return vertices; } -bool jpsRoom::ContainsDoor(jpsLineItem *lineItem) const +void jpsRoom::AddDoor(jpsCrossing *door) { - QList<QPointF> vertices = GetDoorVertices(); - - for (QPointF vertex:vertices) - { - if (lineItem->get_line()->contains(vertex)) - { - return true; - } - } - return false; + _doorList.push_back(door); +} +QPolygonF jpsRoom::RoomAsPolygon() const +{ + return QPolygonF(get_vertices()); } +//bool jpsRoom::ContainsDoor(jpsLineItem *lineItem) const +//{ +// QList<QPointF> vertices = GetDoorVertices(); + +// for (QPointF vertex:vertices) +// { +// if (lineItem->get_line()->contains(vertex)) +// { +// return true; +// } +// } +// return false; + +//} + void jpsRoom::set_id(int id_room) diff --git a/src/rooms.h b/src/rooms.h index f39baba38d31ddfd56f56ce22a4f1a5b9233c7fb..33f8d03ad011094f6e3fe3472eca7ae91a26d949 100644 --- a/src/rooms.h +++ b/src/rooms.h @@ -32,6 +32,8 @@ #include <QGraphicsView> #include "jpsLineItem.h" +class jpsCrossing; + class jpsRoom { @@ -45,7 +47,7 @@ public: void change_name(QString name); QList<jpsLineItem*> get_listWalls(); void activate(); - QList<QPointF> get_vertices(); + QVector<QPointF> get_vertices() const; void set_id(int id_room); int get_id(); QPointF get_center(); @@ -53,7 +55,9 @@ public: QString get_type(); void set_type(const QString &string); QList<QPointF> GetDoorVertices() const; - bool ContainsDoor(jpsLineItem* lineItem) const; + //bool ContainsDoor(jpsLineItem* lineItem) const; + void AddDoor(jpsCrossing *door); + QPolygonF RoomAsPolygon() const; private: @@ -62,6 +66,8 @@ private: QString name; QList<jpsLineItem*> item_list; QString _type; + QList<jpsCrossing* > _doorList; + }; diff --git a/src/roomwidget.cpp b/src/roomwidget.cpp index 57d8a33ed577516e2d9dc62f05df4b975ef01b67..2b705cdbf74dfec94406ea961c76c3cc5ec6e737 100644 --- a/src/roomwidget.cpp +++ b/src/roomwidget.cpp @@ -85,7 +85,7 @@ roomWidget::roomWidget(QWidget *parent, jpsDatamanager *dmanager, jpsGraphicsVie connect(ui->roomBox2,SIGNAL(activated(int)),this,SLOT(add_rooms_to_crossing())); connect(ui->removeCrossingButton,SIGNAL(clicked(bool)),this,SLOT(delete_crossing())); connect(ui->crossingList,SIGNAL(itemClicked(QListWidgetItem*)),this,SLOT(select_crossing())); - connect(ui->auto_assign_doors,SIGNAL(clicked(bool)),this,SLOT(autoAssignDoors())); + //connect(ui->auto_assign_doors,SIGNAL(clicked(bool)),this,SLOT(autoAssignDoors())); //tab exit // connect(ui->addExitButton,SIGNAL(clicked(bool)),this,SLOT(new_exit())); // connect(ui->exitList,SIGNAL(itemClicked(QListWidgetItem*)),this,SLOT(enable_roomSelectionExits())); @@ -767,20 +767,20 @@ void roomWidget::highlight_obs() } -void roomWidget::autoAssignDoors() -{ - datamanager->AutoAssignCrossings(); - show_all(); - enable_roomSelectionCrossings(); -} +//void roomWidget::autoAssignDoors() +//{ +// datamanager->AutoAssignCrossings(); +// show_all(); +// enable_roomSelectionCrossings(); +//} -void roomWidget::autoAssignExits() -{ - datamanager->AutoAssignExits(); - show_all(); - enable_roomSelectionExits(); +//void roomWidget::autoAssignExits() +//{ +// datamanager->AutoAssignExits(); +// show_all(); +// enable_roomSelectionExits(); -} +//} void roomWidget::ChangeRoomType() { diff --git a/src/roomwidget.h b/src/roomwidget.h index 7c8b072f60a4e270a7968d71fe4d3311705841ff..ba1365866b45b771ea273080885ccd7094db050a 100644 --- a/src/roomwidget.h +++ b/src/roomwidget.h @@ -85,8 +85,8 @@ protected slots: bool shhi_roomCaption(); void highlight_room(); void highlight_obs(); - void autoAssignDoors(); - void autoAssignExits(); +// void autoAssignDoors(); +// void autoAssignExits(); void ChangeRoomType();