diff --git a/TraVisTo.pro b/TraVisTo.pro index be3597f843ec09256659118e25cbf5a84616a44b..40e25e4f9600a2d3e815d8987bac44697bc16739 100644 --- a/TraVisTo.pro +++ b/TraVisTo.pro @@ -1,9 +1,9 @@ TEMPLATE = app TARGET = TraVisTo CONFIG += qt -QT += xml \ - network -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets +QT += xml network + +greaterThan(QT_MAJOR_VERSION, 4):QT += widgets win32 { INCLUDEPATH += C:/VTK/include/vtk-6.1 @@ -104,7 +104,7 @@ win32 { -lvtkRenderingFreeType-6.1 \ -lvtkRenderingFreeTypeOpenGL-6.1 \ -lvtkRenderingGL2PS-6.1 \ - -lvtkRenderingHybridOpenGL-6.1 \ +# -lvtkRenderingHybridOpenGL-6.1 \ -lvtkRenderingImage-6.1 \ -lvtkRenderingLabel-6.1 \ -lvtkRenderingLOD-6.1 \ @@ -113,7 +113,7 @@ win32 { -lvtkRenderingVolume-6.1 \ -lvtkRenderingVolumeAMR-6.1 \ -lvtkRenderingVolumeOpenGL-6.1 \ - -lvtksqlite-6.1 \ + # -lvtksqlite-6.1 \ -lvtksys-6.1 \ -lvtktiff-6.1 \ -lvtkverdict-6.1 \ @@ -123,7 +123,7 @@ win32 { -lvtkViewsInfovis-6.1 \ -lvtkViewsQt-6.1 \ -lvtkzlib-6.1 \ - # -lwsock32 + -lwsock32 } win32er { INCLUDEPATH += C:/VTK/include/vtk-5.10 @@ -278,7 +278,78 @@ unix { -lvtkzlib-6.0 \ } - HEADERS += forms/Settings.h \ +win323{ + INCLUDEPATH += C:/VTK/include/vtk-5.10 + LIBS += -LC:/VTK/bin \ + -lvtksys \ + -lvtkzlib \ + -lvtkjpeg \ + -lvtkpng \ + -lvtktiff \ + -lvtkexpat \ + -lvtkfreetype \ + -lvtklibxml2 \ + -lvtkDICOMParser \ + -lvtkverdict \ + -lvtkNetCDF \ + -lvtkmetaio \ + -lvtkexoIIc \ + -lvtkalglib \ + -lvtkftgl \ + -lvtkCommon \ + -lvtkFiltering \ + -lvtkImaging \ + -lvtkGraphics \ + -lvtkIO \ + -lvtkRendering \ + -lvtkParallel \ + -lvtkHybrid \ + -lvtkWidgets \ + -lvtkInfovis \ + -lvtkViews \ + -lwsock32 \ + } + unix { + INCLUDEPATH += /usr/include/vtk-5.8 + LIBS += -L/usr/lib/ \ + -lvtkCommon \ + -lvtkDICOMParser \ + -lvtkFiltering \ + -lvtkGenericFiltering \ + -lvtkGraphics \ + -lvtkHybrid \ + -lvtkIO \ + -lvtkImaging \ + -lvtkRendering \ + -lvtkVolumeRendering \ + -lvtkWidgets \ + -lvtkexoIIc \ + -lvtkftgl \ + -lvtksys \ + -lvtkverdict \ + -lvtkParallel \ + -lvtkmetaio + } + + HEADERS += src/geometry/Building.h \ + src/geometry/Crossing.h \ + src/geometry/Goal.h \ + src/geometry/Hline.h \ + src/geometry/Line.h \ + src/geometry/NavLine.h \ + src/geometry/Obstacle.h \ + src/geometry/Point.h \ + src/geometry/Room.h \ + src/geometry/SubRoom.h \ + src/geometry/Transition.h \ + src/geometry/Wall.h \ + src/geometry/JPoint.h \ + src/tinyxml/tinystr.h \ + src/tinyxml/tinyxml.h \ + src/general/Macros.h \ + src/IO/OutputHandler.h \ + src/IO/TraVisToClient.h \ + forms/Settings.h \ src/SaxParser.h \ src/Debug.h \ src/travisto.h \ @@ -296,28 +367,31 @@ unix { src/extern_var.h \ src/geometry/FacilityGeometry.h \ src/geometry/LinePlotter.h \ - src/geometry/Point.h \ src/geometry/PointPlotter.h \ src/geometry/LinePlotter2D.h \ src/geometry/PointPlotter2D.h \ - src/geometry/jul/Building.h \ - src/geometry/jul/Room.h \ - src/geometry/jul/Line.h \ - src/geometry/jul/Transition.h \ - src/geometry/jul/Wall.h \ - src/geometry/jul/CPoint.h \ - src/geometry/jul/Macros.h \ - src/geometry/pg3/CLine.h \ - src/geometry/pg3/CBuilding.h \ - src/geometry/pg3/CRoom.h \ - src/geometry/pg3/CCell.h \ - src/geometry/pg3/CCoordsList.h \ - src/geometry/pg3/Common.h \ - src/geometry/pg3/CTextLog.h \ - src/geometry/pg3/CTransition.h \ src/network/TraVisToServer.h - SOURCES += forms/Settings.cpp \ + SOURCES += src/geometry/Building.cpp \ + src/geometry/Crossing.cpp \ + src/geometry/Goal.cpp \ + src/geometry/Hline.cpp \ + src/geometry/Line.cpp \ + src/geometry/NavLine.cpp \ + src/geometry/Obstacle.cpp \ + src/geometry/Point.cpp \ + src/geometry/Room.cpp \ + src/geometry/SubRoom.cpp \ + src/geometry/Transition.cpp \ + src/geometry/Wall.cpp \ + src/geometry/JPoint.cpp \ + src/tinyxml/tinystr.cpp \ + src/tinyxml/tinyxml.cpp \ + src/tinyxml/tinyxmlerror.cpp \ + src/tinyxml/tinyxmlparser.cpp \ + src/IO/OutputHandler.cpp \ + src/IO/TraVisToClient.cpp \ + forms/Settings.cpp \ src/SaxParser.cpp \ src/Debug.cpp \ src/main.cpp \ @@ -336,22 +410,7 @@ unix { src/geometry/PointPlotter2D.cpp \ src/geometry/FacilityGeometry.cpp \ src/geometry/LinePlotter.cpp \ - src/geometry/Point.cpp \ src/geometry/PointPlotter.cpp \ - src/geometry/jul/Building.cpp \ - src/geometry/jul/Room.cpp \ - src/geometry/jul/Line.cpp \ - src/geometry/jul/Transition.cpp \ - src/geometry/jul/Wall.cpp \ - src/geometry/jul/CPoint.cpp \ - src/geometry/pg3/CLine.cpp \ - src/geometry/pg3/CBuilding.cpp \ - src/geometry/pg3/CRoom.cpp \ - src/geometry/pg3/CCell.cpp \ - src/geometry/pg3/CCoordsList.cpp \ - src/geometry/pg3/Common.cpp \ - src/geometry/pg3/CTextLog.cpp \ - src/geometry/pg3/CTransition.cpp \ src/network/TraVisToServer.cpp FORMS += forms/settings.ui \ forms/travisto.ui diff --git a/forms/Settings.h b/forms/Settings.h index 4853fc9e8515fbc9a1f3689e203bbeb1c99e58bd..f8825ca5755a27aa64eb4a8285a16cf9f77fbda7 100644 --- a/forms/Settings.h +++ b/forms/Settings.h @@ -32,7 +32,7 @@ #ifndef PEDESTRIANSHAPE_H #define PEDESTRIANSHAPE_H -#include <QtGui/QWidget> +#include <QWidget> #include "ui_settings.h" #include "./src/SystemSettings.h" diff --git a/src/Frame.cpp b/src/Frame.cpp index 481c1e3e08b1355fb7d3fe2df1d8c431b6a34d66..2cc5a06bbc581b7c8d55827f555657d520a870ce 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -114,6 +114,7 @@ vtkPolyData* Frame::GetPolyData() { VTK_CREATE (vtkPoints, points); VTK_CREATE (vtkFloatArray, colors); colors->SetName("color"); + //colors->SetNumberOfComponents(3); colors->SetNumberOfComponents(1); for (unsigned int i=0;i<framePoints.size();i++){ double pos[3]; @@ -121,7 +122,12 @@ vtkPolyData* Frame::GetPolyData() { framePoints[i]->getPos(pos); framePoints[i]->getEllipse(data); points->InsertNextPoint(pos); + if(data[6]==-1){ + colors->InsertNextValue(NAN); + } + else{ colors->InsertNextValue(data[6]/255.0); + } } //scalars->Print(cout); VTK_CREATE (vtkFloatArray, data); diff --git a/src/IO/OutputHandler.cpp b/src/IO/OutputHandler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1fb1428f9382d8d2e986b63c7c37927322656921 --- /dev/null +++ b/src/IO/OutputHandler.cpp @@ -0,0 +1,128 @@ +/** + * File: OutputHandler.cpp + * + * Created on 20. November 2010, 15:20 + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#include "OutputHandler.h" + +#include <stdio.h> +#include <stdarg.h> +#include <cstdlib> + +using namespace std; + + +void OutputHandler::Write(string str) { + if (this != NULL) + cout << str << endl; +} + +void OutputHandler::Write(const char* message,...) { + char msg[CLENGTH]; + va_list ap; + va_start (ap, message); + vsprintf (msg,message ,ap); + va_end (ap); + + string str(msg); + if(str.find("ERROR")==string::npos) { + cout<<msg<<endl; + cout.flush(); + } + else { + cerr<<msg<<endl; + cerr.flush(); + } + + //cout << "\033[1;30mbold red text\033[0m\n"; + //cout << "\033[1;31"<<msg<<"\033[0m\n"; + //cout << "\033[1;31 bla bla \033[0m\n"; +} + +void STDIOHandler::Write(string str) { + if (this != NULL) + cout << str << endl; +} + +FileHandler::FileHandler(const char *fn) { + pfp.open(fn); + if (!fn) { + char tmp[CLENGTH]; + sprintf(tmp, "Error!!! File [%s] could not be opened!", fn); + cerr << tmp << endl; + exit(0); + } +} + +FileHandler::~FileHandler() { + pfp.close(); +} + +void FileHandler::Write(string str) { + if (this != NULL) { + pfp << str << endl; + pfp.flush(); + } +} + +void FileHandler::Write(const char* string,...) { + char msg[CLENGTH]; + va_list ap; + va_start (ap, string); + vsprintf (msg,string ,ap); + va_end (ap); + pfp<<msg<<endl; + pfp.flush(); +} + +TraVisToHandler::TraVisToHandler(string host, int port) { + client = new TraVisToClient(host, port); + brokentags.push_back("<trajectoriesDataset>"); + brokentags.push_back("</trajectoriesDataset>"); + brokentags.push_back("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); +} + +TraVisToHandler::~TraVisToHandler(){ + delete client; +} + +void TraVisToHandler::Write(string str) { + + vector<string>::iterator str_it; + + //There are a few broken tags which need to be checked for and removed. + for (str_it = brokentags.begin(); str_it != brokentags.end(); ++str_it) { + int tagstart = str.find(*str_it); + if (tagstart != (int) string::npos) { + str.erase(str.begin() + tagstart, str.begin() + tagstart + (*str_it).size()); + } + } + client->sendData(str.c_str()); +} + + + + + diff --git a/src/IO/OutputHandler.h b/src/IO/OutputHandler.h new file mode 100644 index 0000000000000000000000000000000000000000..855d85ad4b6f72f53d0b82e510767cf822fff2b6 --- /dev/null +++ b/src/IO/OutputHandler.h @@ -0,0 +1,79 @@ +/** + * File: OutputHandler.h + * + * Created on 20. November 2010, 15:20 + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#ifndef OUTPUT_HANDLER_H_ +#define OUTPUT_HANDLER_H_ + +#include <iostream> +#include <fstream> +#include <vector> + + +#include "../IO/TraVisToClient.h" +#include "../general/Macros.h" + +class 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); +}; + +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,...); +}; + +class TraVisToHandler : public OutputHandler { +private: + TraVisToClient* client; + +public: + TraVisToHandler(std::string host, int port); + virtual ~TraVisToHandler(); + void Write(std::string str); + + //Some tags are broken + std::vector<std::string> brokentags; +}; + + + + +#endif /*OUTPUT_HANDLER_H_*/ + diff --git a/src/IO/TraVisToClient.cpp b/src/IO/TraVisToClient.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d095a4bbfb0281858ed271f4fe717725547b819c --- /dev/null +++ b/src/IO/TraVisToClient.cpp @@ -0,0 +1,498 @@ +/** + * TraVisToClient.cpp + * Copyright (C) <2009-2010> <Ulrich Kemloh> + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + + +/********* include files ******************************************************/ + +#include <iostream> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + + +#include "TraVisToClient.h" + + +using namespace std; + +TraVisToClient::TraVisToClient(string hostname, unsigned short port) { + _hostname=hostname; + _port = port; + _isConnected = false; + createConnection(); + + +} + +TraVisToClient::~TraVisToClient() { + if (_isConnected) close(); +} + + +/// send datablock to the server + +void TraVisToClient::sendData(const char* data) { + + // first create a new connection, in the case the last one was lost/close + + if (!_isConnected) { + createConnection(); + //FIXME: queue messsage in a vector + // msgQueue.push_back(data); + return; + + } + char msgSizeStr[10]; + int msgSize = (int)strlen(data); + sprintf(msgSizeStr, "%d\n", msgSize); + + /* check if parameters are valid */ + if (NULL == data) { + fprintf(stderr, "invalid message buffer!"); + fprintf(stderr, "leaving sendMessage()"); + _isConnected = false; + return; + } + + + // do until queue empty for() + + + /*send the length of the message*/ + int msgsize = strlen(msgSizeStr); + if (msgsize != send(_tcpSocket, (const char *) msgSizeStr, strlen(msgSizeStr), 0)) { + fprintf(stderr, "sending message Size failed"); + fprintf(stderr, "leaving sendMessage()"); + _isConnected = false; + return; + } + + /* now send the message */ + if (msgSize != send(_tcpSocket, (const char *) data, msgSize, 0)) { + fprintf(stderr, "sending message failed"); + fprintf(stderr, "leaving sendMessage()"); + _isConnected = false; + return; + } + + // end do +} + +/// close the client (end the connection) + +void TraVisToClient::close() { + if (_isConnected) { + /* all things are done, so shutdown the connection */ + if (!shutdownAndCloseSocket(_tcpSocket)) { + fprintf(stderr, "shutdown and close socket failed!"); + stopSocketSession(); + fprintf(stderr, "leaving main() with error"); + return; + } + + /* stop the socket session */ + stopSocketSession(); + } + +} + +void TraVisToClient::createConnection() { + + /* start the socket session */ + if (!startSocketSession()) { + fprintf(stderr, "startSocketSession() failed!"); + fprintf(stderr, "socket creation failed for host [%s] on port [%d]!",_hostname.c_str(),_port); + exit(EXIT_FAILURE); + } + + /* create a new socket and connect the socket to the given service */ + if (INVALID_SOCKET == (_tcpSocket = createClientSocket(_hostname.c_str(), _port))) { + fprintf(stderr, "\nsocket creation failed for host [%s] on port [%d]!\n",_hostname.c_str(),_port); + stopSocketSession(); + exit(EXIT_FAILURE); + } + _isConnected = true; +} + +/********* function definitions **************************************/ + +/** + * This function returns an integer (unsigned long) representation + * of an IP address, given as a FQN or a dotted IP address. + * + * @param hostName name of a host as FQN or dotted IP address + * + * @return The return value is an integer value of a dotted IP address if + * the hostname exists (valid DNS entry) or the hostname is given + * as a dotted IP address. Otherwise the function returns + * @c INADDR_NONE. + */ +unsigned long +TraVisToClient::lookupHostAddress(const char *hostName) { + unsigned long addr; /* inet address of hostname */ + struct hostent *host; /* host structure for DNS request */ + + dtrace("entering lookupHostAddress()"); + + if (NULL == hostName) { + derror("invalid parameter"); + dtrace("leaving lookupHostAddress()"); + return (INADDR_NONE); + } + + dtrace("looking for host %s", hostName); + + addr = inet_addr(hostName); + + if (INADDR_NONE == addr) { + /* hostName isn't a dotted IP, so resolve it through DNS */ + host = gethostbyname(hostName); + if (NULL != host) { + addr = *((unsigned long *) host->h_addr); + } + } + + dtrace("leaving lookupHostAddress()"); + return (addr); +} +/******** end of function lookupHostAddress **************************/ + +/** + * This function creates a new client internet domain socket (TCP/IP) + * and connects to a service on an internet host. + * + * @param serverName hostname of a server + * @param portNumber port number of service + * + * @return The function returns a socket handle if the socket can be created + * and connected to a service. If an error occurred, the function + * returns @c INVALID_SOCKET. + */ +socket_t +TraVisToClient::createClientSocket(const char *serverName, unsigned short portNumber) { + unsigned long ipAddress; /* internet address */ + struct sockaddr_in srvAddr; /* server's internet socket address */ + socket_t sock; /* file descriptor for client socket */ + + dtrace("entering createClientSocket()"); + + /* get the IP address of the server host */ + if (INADDR_NONE == (ipAddress = lookupHostAddress(serverName))) { + derror("lookupHostAddress() failed"); + dtrace("leaving createClientSocket() with INVALID_SOCKET"); + return (INVALID_SOCKET); + } + + dtrace("trying to connect %s on port %hu", serverName, portNumber); + + /* create the client socket */ + if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP))) { + derror("socket creation failed"); + dtrace("leaving createClientSocket() with INVALID_SOCKET"); + return (INVALID_SOCKET); + } + + /* fill the server address structure */ + memset(&srvAddr, 0, sizeof (srvAddr)); + srvAddr.sin_family = AF_INET; + srvAddr.sin_port = htons(portNumber); + srvAddr.sin_addr.s_addr = ipAddress; + + /* try to connect to the server socket */ + if (SOCKET_ERROR == connect(sock, (struct sockaddr *) & srvAddr, sizeof (srvAddr))) { + derror("connect() failed"); + //FIXME + //closesocket(tcpSocket); + dtrace("leaving createClientSocket() with INVALID_SOCKET"); + return (INVALID_SOCKET); + } + + dtrace("leaving createClientSocket()"); + return (sock); +} +/******** end of function createClientSocket *************************/ + +/** + * This function creates a new server internet domain socket (TCP/IP). + * + * @param portNumber port number on which to listen for incoming packets + * + * @return The function returns a socket handle if the socket can be created. + * If an error occurs, the function returns @c INVALID_SOCKET. + */ +socket_t +TraVisToClient::createServerSocket(unsigned short portNumber) { + struct sockaddr_in srvAddr; /* server's internet socket address */ + socket_t sock; /* file descriptor for server socket */ + + dtrace("entering createServerSocket()"); + + /* create the server socket */ + if (INVALID_SOCKET == (sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP))) { + derror("socket creation failed"); + dtrace("leaving createServerSocket() with INVALID_SOCKET"); + return (INVALID_SOCKET); + } + + /* fill the server address structure */ + /* first of all, zero srvAddr, so that we have a defined status */ + memset(&srvAddr, 0, sizeof (srvAddr)); + srvAddr.sin_family = AF_INET; + srvAddr.sin_port = htons(portNumber); + srvAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + /* try to bind socket to the specified server port */ + if (SOCKET_ERROR == bind(sock, (struct sockaddr *) & srvAddr, sizeof (srvAddr))) { + derror("bind() failed!"); + //FIXME: + //closesocket(tcpSocket); + dtrace("leaving createServerSocket() with INVALID_SOCKET"); + return (INVALID_SOCKET); + } + + if (SOCKET_ERROR == listen(sock, QUEUE_LENGTH)) { + derror("listen() failed!"); + shutdownAndCloseSocket(sock); + dtrace("leaving createServerSocket() with INVALID_SOCKET"); + return (INVALID_SOCKET); + } + + dtrace("server started at port %hu", portNumber); + + dtrace("leaving createServerSocket()"); + return (sock); +} +/******** end of function createServerSocket *************************/ + +/** + * This function sends a message of a given size to a communication + * partner via a connected socket. + * + * @param sock socket for sending the message + * @param msg pointer to the message buffer which should be sent + * @param msgSize size of the message buffer + * + * @return The function returns @c true if the message was sent to the server, + * otherwise the function returns @c false. + */ +bool +TraVisToClient::sendMessage(socket_t sock, const void *msg, int msgSize) { + dtrace("entering sendMessage()"); + + /* check if parameters are valid */ + if (NULL == msg) { + derror("invalid message buffer!"); + dtrace("leaving sendMessage()"); + return (false); + } + + if (0 >= msgSize) { + derror("invalid message size %d", msgSize); + dtrace("leaving sendMessage()"); + return (false); + } + + dtrace("sending message of size %d", msgSize); + + /* now send the message */ + if (msgSize != send(sock, (const char *) msg, msgSize, 0)) { + derror("sending message failed"); + dtrace("leaving sendMessage()"); + return (false); + } + + dtrace("leaving sendMessage()"); + return (true); +} +/******** end of function sendMessage ********************************/ + +/** + * This functions receives a message from a communication partner and + * stores it into a given message buffer. + * The function blocks until all bytes have been successfully received, + * or an error occurred. + * + * @param sock socket for receiving the message + * @param[out] msg message buffer for receiving the message + * @param msgSize size of the buffer to contain the message + * + * @return The function returns @c true if all things went well. Otherwise + * the function returns @c false. + */ +bool +TraVisToClient::receiveMessage(socket_t sock, void *msg, int msgSize) { + char *msgPart; /* pointer to the memory for receiving the message */ + int toReceive; /* number of bytes to receive */ + int received; /* number of bytes totally received */ + int nBytes; /* number of bytes currently received */ + + dtrace("entering receiveMessage()"); + + /* check if parameters are valid */ + if (NULL == msg) { + derror("invalid message buffer!"); + dtrace("leaving receiveMessage()"); + return (false); + } + + if (0 >= msgSize) { + derror("invalid message size!"); + dtrace("leaving receiveMessage()"); + return (false); + } + + msgPart = (char *) msg; + received = 0; + + dtrace("trying to receive a message of size %d", msgSize); + + /* start receiving bytes from server until complete message is received */ + do { + toReceive = msgSize - received; + nBytes = recv(sock, msgPart, toReceive, 0); + switch (nBytes) { + case SOCKET_ERROR: /* error occurred */ + derror("error during message receipt"); + dtrace("leaving receiveMessage()"); + return (false); + case 0: /* connection has been closed */ + derror("remote host has closed the connection"); + dtrace("leaving receiveMessage()"); + return (false); + default: /* some bytes have been received */ + dtrace("received %d bytes of message", nBytes); + received += nBytes; + msgPart += nBytes; + break; + } + } while (received != msgSize); + + dtrace("received message of size %d", received); + + dtrace("leaving receiveMessage()"); + return (true); +} +/******** end of function receiveMessage *****************************/ + +/** + * This function shuts down and closes a given socket. + * + * @param sock socket to be closed + * + * @return if all things went ok, this function returns @c true, otherwise + * @c false + */ +bool +TraVisToClient::shutdownAndCloseSocket(socket_t sock) { + bool status = true; + + dtrace("entering shutdownAndCloseSocket()"); + + if (SOCKET_ERROR == shutdown(sock, SHUT_RDWR)) { + derror("shutdown() failed"); + status = false; + } + + //FIXME: + //if (SOCKET_ERROR == closesocket(tcpSocket)) { + // derror("closesocket() failed"); + // status = false; + //} + + dtrace("leaving shutdownAndCloseSocket()"); + return (status); +} + +/******** end of function shutdownAndCloseSocket *********************/ + +void +TraVisToClient::_printErrorMessage(void) { +} + + +#ifdef _WIN32 + +/** + * This function initializes the Win32 Socket API. + * + * @return if all things went ok, this function returns @c true, otherwise + * @c false + */ +bool +TraVisToClient::_startWin32SocketSession(void) { + WORD requestedVersion; + WSADATA wsaData; + + dtrace("entering _startWin32SocketSession()"); + + requestedVersion = MAKEWORD(WS_MAJOR_VERSION, WS_MINOR_VERSION); + + if (0 != WSAStartup(requestedVersion, &wsaData)) { + derror("WSAStartup() failed"); + dtrace("leaving _startWin32SocketSession() with error"); + return (false); + } + + /* Confirm that the Windows Socket DLL supports 1.1. */ + /* Note that if the DLL supports versions greater */ + /* than 1.1 in addition to 1.1, it will still return */ + /* 1.1 in wVersion since that is the version we */ + /* requested. */ + + if (WS_MINOR_VERSION != LOBYTE(wsaData.wVersion) + || WS_MAJOR_VERSION != HIBYTE(wsaData.wVersion)) { + derror("Windows Socket DLL does not support the requested version"); + _stopWin32SocketSession(); + dtrace("leaving _startWin32SocketSession() with error"); + return (false); + } + + WSASetLastError(0); /* reset the error code */ + + dtrace("leaving _startWin32SocketSession()"); + return (true); +} +/******** end of function _startWin32SocketSession *******************/ + +/** + * This function terminates the Win32 Socket API. + * No future API calls are allowed. + */ +void +TraVisToClient::_stopWin32SocketSession(void) { + dtrace("entering _stopWin32SocketSession()"); + + if (SOCKET_ERROR == WSACleanup()) { + derror("WSACleanup() failed"); + } + + dtrace("leaving _stopWin32SocketSession()"); + return; +} +/******** end of function _stopWin32SocketSession ********************/ + +#endif /* _WIN32 */ + diff --git a/src/IO/TraVisToClient.h b/src/IO/TraVisToClient.h new file mode 100644 index 0000000000000000000000000000000000000000..9b37e54ebfc18bad87eff0ea5c2261350bec36eb --- /dev/null +++ b/src/IO/TraVisToClient.h @@ -0,0 +1,149 @@ +/** + * + * Copyright (C) <2009-2010> <Ulrich Kemloh> + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#ifndef TRAVISTOCLIENT_H_ +#define TRAVISTOCLIENT_H_ + +#include <iostream> +#include <vector> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> + +#ifdef _WIN32 + +#endif + +#define QUEUE_LENGTH 5 ///< max queue length of pending connections + +/******** macro definitions ******************************************/ + +#ifdef TRACE_LOGGING + +#define dtrace(...) _printDebugLine(__FILE__, __LINE__, false, __VA_ARGS__) +#define derror(...) _printDebugLine(__FILE__, __LINE__, true, __VA_ARGS__) + +#else + +#define dtrace(...) ((void) 0) +#define derror(...) (fprintf(stderr, __VA_ARGS__), _printErrorMessage()) + +#endif /* TRACE_LOGGING */ + + +#ifdef _WIN32 +#include <winsock.h> +#define WS_MAJOR_VERSION 1 ///< major version of Winsock API +#define WS_MINOR_VERSION 1 ///< minor version of Winsock API +#define SHUT_RDWR 2 ///< @c SHUT_RDWR is POSIX standard +typedef SOCKET socket_t; +typedef int socklen_t; +#define startSocketSession() _startWin32SocketSession() +#define stopSocketSession() _stopWin32SocketSession() + + +#else +#include <unistd.h> +#include <netinet/in.h> +#include <netdb.h> +#include <arpa/inet.h> +#include <sys/socket.h> +typedef int socket_t; +#define u_int_32_t unsigned int +#define startSocketSession() (true) +#define stopSocketSession() ((void) 0) +//#define closesocket close +#define INVALID_SOCKET (-1) +#define SOCKET_ERROR (-1) +#endif + + +#ifndef IPPORT_USERRESERVED +#define IPPORT_USERRESERVED (5000) ///< up to this number, ports are reserved and should not be used +#endif + + + +#define PORT 8989 +#define HOST "localhost" + +class TraVisToClient { +public: + + /// create a client with specific parameters + TraVisToClient(std::string hostname = HOST, unsigned short port = PORT); + + /// 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); + + /// close the client (end the connection) + void close(); + + /// send a datagram using the unreliable + /// udp protokoll + void sendDatagram(char *datagram); + +private: + void createConnection(); + + unsigned long lookupHostAddress(const char *hostName); + + socket_t createClientSocket(const char *serverName, unsigned short portNumber); + + socket_t createServerSocket(unsigned short portNumber); + + bool shutdownAndCloseSocket(socket_t sock); + + bool sendMessage(socket_t sock, const void *msg, int msgSize); + + bool receiveMessage(socket_t sock, void *msg, int msgSize); + + void _printErrorMessage(void); + +#ifdef _WIN32 + bool _startWin32SocketSession(void); + void _stopWin32SocketSession(void); +#else + #define closesocket close +#endif + + + +private: + bool _isConnected; + socket_t _tcpSocket; + std::string _hostname; + unsigned short _port; + std::vector<const char *> _msgQueue; + +}; + +#endif /* TRAVISTOCLIENT_H_ */ diff --git a/src/InteractorStyle.cpp b/src/InteractorStyle.cpp index 6be369cb60e3b0c2f799c9e1de3efbb1f44989ff..61fcbb1733af55dd02289070c815cffe6b5982c9 100644 --- a/src/InteractorStyle.cpp +++ b/src/InteractorStyle.cpp @@ -71,7 +71,7 @@ void InteractorStyle::SetSource() { //forward the event only if not in 2d mode void InteractorStyle::Rotate() { - if(!SystemSettings::get2D()) + //if(!SystemSettings::get2D()) vtkInteractorStyleTrackballCamera::Rotate(); } diff --git a/src/Pedestrian.cpp b/src/Pedestrian.cpp index 2cad38822516e7021732c6e475a9520314fbfd83..5cc3a350951043380b0a89b0895a91cfb8545684 100644 --- a/src/Pedestrian.cpp +++ b/src/Pedestrian.cpp @@ -32,7 +32,7 @@ //http://www.mail-archive.com/paraview@paraview.org/msg02142.html #include "Pedestrian.h" -#include "geometry/Point.h" +#include "geometry/JPoint.h" #include "geometry/PointPlotter.h" #include "geometry/LinePlotter.h" #include "forms/Settings.h" @@ -1523,7 +1523,7 @@ void Pedestrian::enableCaption(bool status){ void Pedestrian::plotTrail(double x, double y, double z){ - trailPoint.push(new Point (x,y,z)); + trailPoint.push(new JPoint (x,y,z)); } @@ -1561,7 +1561,7 @@ void Pedestrian::triggerPlotTrail() { // trailPlotterLine->addVertex(first); while (!trailPoint.isEmpty()){ - Point * next = trailPoint.pop(); + JPoint * next = trailPoint.pop(); next->setColorRGB(pedsColors[0],pedsColors[1],pedsColors[2]); //trailPlotterLine->PlotLine(first, next); diff --git a/src/Pedestrian.h b/src/Pedestrian.h index 4d699a2d0cf8acca5f8f161639296b2d0cd4c312..0e63744c19e48e488c4ba4f835f03d29dafcf29b 100644 --- a/src/Pedestrian.h +++ b/src/Pedestrian.h @@ -44,7 +44,7 @@ class vtkDataArray; class vtkTextActor3D ; class PointPlotter; class LinePlotter; -class Point; +class JPoint; class vtkPoints; class TrajectoryPoint; class vtkCamera; @@ -232,7 +232,7 @@ private : vtkTextActor3D* caption; /// trails plotter - QStack<Point*> trailPoint; + QStack<JPoint*> trailPoint; PointPlotter* trailPlotterPoint; LinePlotter* trailPlotterLine; }; diff --git a/src/SaxParser.cpp b/src/SaxParser.cpp index aae6141d2679575614a5aa55526391169ca28e99..9650d2e6f82cd6f19278b2fe60d837b9a291ea74 100644 --- a/src/SaxParser.cpp +++ b/src/SaxParser.cpp @@ -33,10 +33,9 @@ #include "SyncData.h" #include "Debug.h" -#include "geometry/Point.h" +#include "geometry/JPoint.h" #include "geometry/FacilityGeometry.h" -#include "geometry/jul/Building.h" -#include "geometry/pg3/CBuilding.h" +#include "geometry/Building.h" #include <QMessageBox> #include <QString> @@ -45,6 +44,20 @@ #include <cmath> +#include <vtkVersion.h> +#include <vtkSmartPointer.h> +#include <vtkPolygon.h> +#include <vtkCellArray.h> +#include <vtkPolyData.h> +#include <vtkPolyDataMapper.h> +#include <vtkActor.h> +#include <vtkRenderWindow.h> +#include <vtkRenderer.h> +#include <vtkRenderWindowInteractor.h> +#include <vtkAssembly.h> +#include <vtkProperty.h> + + using namespace std; /** @@ -88,13 +101,9 @@ bool SaxParser::startElement(const QString & /* namespaceURI */, QString fileName=at.value(i); if(!fileName.isEmpty()) { - if(fileName.endsWith(".jul",Qt::CaseInsensitive)) - { - SaxParser::parseGeometryJUL(fileName,geometry); - } - else if (fileName.endsWith(".pg3",Qt::CaseInsensitive)) + if(fileName.endsWith(".xml",Qt::CaseInsensitive)) { - SaxParser::parseGeometryPG3(fileName,geometry); + SaxParser::parseGeometryJPS(fileName,geometry); } else if (fileName.endsWith(".trav",Qt::CaseInsensitive)) { @@ -373,7 +382,7 @@ bool SaxParser::startElement(const QString & /* namespaceURI */, } double CHT[3]={color,height,thickness}; - Point* pt= new Point(xPos,yPos,zPos); + JPoint* pt= new JPoint(xPos,yPos,zPos); pt->setColorHeightThicknes(CHT); currentPointsList.push_back(pt); @@ -604,94 +613,152 @@ void SaxParser::clearPoints(){ /// provided for convenience and will be removed in the next version -void SaxParser::parseGeometryJUL(QString fileName, FacilityGeometry *geometry){ +void SaxParser::parseGeometryJPS(QString fileName, FacilityGeometry *geometry){ - if(!fileName.endsWith(".jul",Qt::CaseInsensitive)) return ; + if(!fileName.endsWith(".xml",Qt::CaseInsensitive)) return ; Building* building = new Building(); string geometrypath = fileName.toStdString(); - // read the geometry - building->LoadFromFile(geometrypath); + building->LoadBuildingFromFile(geometrypath); + building->InitGeometry(); // create the polygons - int anz_rooms=building->GetAllRooms().size(); + int currentID=0; + // Setup the points + vtkSmartPointer<vtkPoints> points = + vtkSmartPointer<vtkPoints>::New(); - for(int i=0; i<anz_rooms; i++) - { - Room r = building->GetRoom(i); - int anz_walls=r.GetAllWalls().size(); - for(int j=0; j<anz_walls; j++) - { - Line l = r.GetWall(j).GetLine(); - geometry->addWall(l.GetPoint1().GetX()*100, l.GetPoint1().GetY()*100,0.0, - l.GetPoint2().GetX()*100, l.GetPoint2().GetY()*100,0.0); - } - int anz_trans = r.GetAllTransitions().size(); - for(int j=0; j<anz_trans; j++) - { - Line l = r.GetTransition(j).GetLine(); - geometry->addDoor(l.GetPoint1().GetX()*100, l.GetPoint1().GetY()*100,0.0, - l.GetPoint2().GetX()*100, l.GetPoint2().GetY()*100,0.0); - } - } + // Add the polygon to a list of polygons + vtkSmartPointer<vtkCellArray> polygons = + vtkSmartPointer<vtkCellArray>::New(); - // free memory - delete building; -} - -/// provided for convenience and will be removed in the next version -void SaxParser::parseGeometryPG3(QString fileName, FacilityGeometry *geometry){ + for (int i = 0; i < building->GetNumberOfRooms(); i++) { + Room* r = building->GetRoom(i); + string caption = r->GetCaption(); - CTextLog* ErrorLog = new CTextLog; - CBuilding* Building = new CBuilding(ErrorLog); - string errorlogpath = "./LogDatei.txt"; - string geometrypath = fileName.toStdString(); + for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { + SubRoom* sub = r->GetSubRoom(k); + const vector<Point>& poly = sub->GetPolygon(); + //if(sub->GetType()!="stair") continue; + //if( ! ( (r->GetID()==1) && (sub->GetSubRoomID()==0))) continue; - // Geometrie einlesen - ErrorLog->AddEntry("INFO: Geometry file: "+geometrypath); - Building->LoadFromFile(geometrypath); - int anz_rooms=(*Building).GetRoomCount(); - CRoom r; + // Create the polygon + vtkSmartPointer<vtkPolygon> polygon = + vtkSmartPointer<vtkPolygon>::New(); + polygon->GetPointIds()->SetNumberOfIds(poly.size()); - for(int i=0; i<anz_rooms; i++) - { - r.CopyData(Building->GetRoom(i)); - float x=r.GetContPos().GetX()*100; - float y=r.GetContPos().GetY()*100; - int z=r.GetZPos()*30000; + for (unsigned int s=0;s<poly.size();s++){ + points->InsertNextPoint(poly[s]._x*FAKTOR,poly[s]._y*FAKTOR,sub->GetElevation(poly[s])*FAKTOR); + polygon->GetPointIds()->SetId(s, currentID++); + //polygon->GetPointIds()->InsertNextId(currentID++); + //cout<<poly[s].toString()<<" : "<<sub->GetElevation(poly[s])<<endl; + } - int anz_lines=r.GetLineElementCount(); - for(int j=0; j<anz_lines; j++) - { - CLine l; - l.CopyData(r.GetLine(j)); - - if(l.GetType()==1) /* WALL */ - geometry->addWall(l.GetPoint1().GetX()*100+x+z, l.GetPoint1().GetY()*100+y,0.0, - l.GetPoint2().GetX()*100+x+z, l.GetPoint2().GetY()*100+y,0.0); - - if(l.GetType()==2) /* STEP */ - geometry->addStep(l.GetPoint1().GetX()*100+x+z, l.GetPoint1().GetY()*100+y,0.0, - l.GetPoint2().GetX()*100+x+z, l.GetPoint2().GetY()*100+y,0.0); - if(l.GetType()==3) /* TRANS */ - geometry->addDoor(l.GetPoint1().GetX()*100+x+z, l.GetPoint1().GetY()*100+y,0.0, - l.GetPoint2().GetX()*100+x+z, l.GetPoint2().GetY()*100+y,0.0); + polygons->InsertNextCell(polygon); } } - // Errorlog speichern - if (errorlogpath.compare("no file")!=0) - ErrorLog->SaveToFile(errorlogpath); + // Create a PolyData + vtkSmartPointer<vtkPolyData> polygonPolyData = + vtkSmartPointer<vtkPolyData>::New(); + polygonPolyData->SetPoints(points); + polygonPolyData->SetPolys(polygons); + + // Create a mapper and actor + vtkSmartPointer<vtkPolyDataMapper> mapper = + vtkSmartPointer<vtkPolyDataMapper>::New(); +#if VTK_MAJOR_VERSION <= 5 + mapper->SetInput(polygonPolyData); +#else + mapper->SetInputData(polygonPolyData); +#endif + + vtkSmartPointer<vtkActor> actor = + vtkSmartPointer<vtkActor>::New(); + actor->SetMapper(mapper); + actor->GetProperty()->SetColor(0,0,1); + actor->GetProperty()->SetOpacity(0.5); + //actor->GetProperty()->SetLineWidth(5); + + geometry->getActor()->AddPart(actor); // free memory - delete Building; - delete ErrorLog; + delete building; } +//void SaxParser::parseGeometryJPS(QString fileName, FacilityGeometry *geometry){ +// +// if(!fileName.endsWith(".xml",Qt::CaseInsensitive)) return ; +// +// Building* building = new Building(); +// string geometrypath = fileName.toStdString(); +// +// // read the geometry +// building->LoadBuildingFromFile(geometrypath); +// building->InitGeometry(); // create the polygons +// +// for (int i = 0; i < building->GetNumberOfRooms(); i++) { +// Room* r = building->GetRoom(i); +// string caption = r->GetCaption(); +// +// for (int k = 0; k < r->GetNumberOfSubRooms(); k++) { +// SubRoom* sub = r->GetSubRoom(k); +// const vector<Point>& poly = sub->GetPolygon(); +// //if(sub->GetType()!="stair") continue; +// if( ! ( (r->GetID()==1) && (sub->GetSubRoomID()==0))) continue; +// // Setup the points +// vtkSmartPointer<vtkPoints> points = +// vtkSmartPointer<vtkPoints>::New(); +// // Create the polygon +// vtkSmartPointer<vtkPolygon> polygon = +// vtkSmartPointer<vtkPolygon>::New(); +// polygon->GetPointIds()->SetNumberOfIds(poly.size()); +// +// for (unsigned int s=0;s<poly.size();s++){ +// points->InsertNextPoint(poly[s]._x*FAKTOR,poly[s]._y*FAKTOR,sub->GetElevation(poly[s])*FAKTOR); +// polygon->GetPointIds()->SetId(s, s); +// } +// +// // Add the polygon to a list of polygons +// vtkSmartPointer<vtkCellArray> polygons = +// vtkSmartPointer<vtkCellArray>::New(); +// polygons->InsertNextCell(polygon); +// +// // Create a PolyData +// vtkSmartPointer<vtkPolyData> polygonPolyData = +// vtkSmartPointer<vtkPolyData>::New(); +// polygonPolyData->SetPoints(points); +// polygonPolyData->SetPolys(polygons); +// +// // Create a mapper and actor +// vtkSmartPointer<vtkPolyDataMapper> mapper = +// vtkSmartPointer<vtkPolyDataMapper>::New(); +//#if VTK_MAJOR_VERSION <= 5 +// mapper->SetInput(polygonPolyData); +//#else +// mapper->SetInputData(polygonPolyData); +//#endif +// +// vtkSmartPointer<vtkActor> actor = +// vtkSmartPointer<vtkActor>::New(); +// actor->SetMapper(mapper); +// actor->GetProperty()->SetColor(0,0,1); +// actor->GetProperty()->SetOpacity(0.5); +// actor->GetProperty()->SetLineWidth(5); +// +// geometry->getActor()->AddPart(actor); +// } +// } +// +// // free memory +// delete building; +//} + + /// provided for convenience and will be removed in the next version void SaxParser::parseGeometryTRAV(QString content, FacilityGeometry *geometry,QDomNode geo){ - cout<<"external geometery fouind"<<endl; + cout<<"external geometry found"<<endl; //creating am empty document // to be filled QDomDocument doc(""); diff --git a/src/SaxParser.h b/src/SaxParser.h index 85b494cfbc559d71a9be702688f4a846caca1a9f..109033dc1ee73cffdd172e10b0a6ef845966403c 100644 --- a/src/SaxParser.h +++ b/src/SaxParser.h @@ -38,7 +38,7 @@ //forwarded classes -class Point; +class JPoint; class TrajectoryPoint; class SyncData; class FacilityGeometry; @@ -64,16 +64,13 @@ public: const QString& value); /// provided for convenience and will be removed in the next version - static void parseGeometryJUL(QString content, FacilityGeometry *geo); - - /// provided for convenience and will be removed in the next version - static void parseGeometryPG3(QString content, FacilityGeometry *geo); + static void parseGeometryJPS(QString content, FacilityGeometry *geo); /// provided for convenience and will be removed in the next version static void parseGeometryXMLV04(QString content, FacilityGeometry *geo); /// provided for convenience and will be removed in the next version - static void parseGeometryTRAV(QString content, FacilityGeometry *geo,QDomNode geoNode=NULL); + static void parseGeometryTRAV(QString content, FacilityGeometry *geo,QDomNode geoNode=QDomNode()); private: //clear the mo @@ -84,7 +81,7 @@ private: QString currentText; QStringList initialPedestriansColors; QStringList initialPedestriansHeights; - std::vector<Point *> currentPointsList; + std::vector<JPoint *> currentPointsList; std::vector<TrajectoryPoint *> currentFrame; bool parsingWalls; diff --git a/src/ThreadVisualisation.cpp b/src/ThreadVisualisation.cpp index 85a5247d998dfa5bcc5a4f36a5caeb58b2290cca..4328d7b9f9a4849a658220023ae180a4fe6f2f18 100644 --- a/src/ThreadVisualisation.cpp +++ b/src/ThreadVisualisation.cpp @@ -79,6 +79,7 @@ #include "SystemSettings.h" #include "Debug.h" #include <vtkSphereSource.h> +#include <vtkCylinderSource.h> #include <vtkWindowToImageFilter.h> #include <vtkActor.h> @@ -435,12 +436,26 @@ void ThreadVisualisation::initGlyphs(){ VTK_CREATE (vtkSphereSource, sphereSource); sphereSource->SetRadius(30); - //sphereSource->SetPhiResolution(20); - //sphereSource->SetThetaResolution(20); + sphereSource->SetPhiResolution(20); + sphereSource->SetThetaResolution(20); + extern_glyphs_pedestrians->SetSourceConnection(sphereSource->GetOutputPort()); + +#if VTK_MAJOR_VERSION <= 5 + extern_glyphs_pedestrians->SetSource(sphereSource->GetOutput()); +#else + extern_glyphs_pedestrians->SetInputConnection(sphereSource->GetOutputPort()); +#endif + + + + //VTK_CREATE (vtkCylinderSource, cylinderSource); + //cylinderSource->SetHeight(160); + //cylinderSource->SetRadius(30); + //extern_glyphs_pedestrians->SetSourceConnection(cylinderSource->GetOutputPort()); + //extern_glyphs_pedestrians->SetInputConnection(cylinderSource->GetOutputPort()); + + - //extern_glyphs_pedestrians->SetSource(sphereSource->GetOutput()); - extern_glyphs_pedestrians->SetSourceConnection(sphereSource->GetOutputPort()); - extern_glyphs_pedestrians->SetInputConnection(sphereSource->GetOutputPort()); extern_glyphs_pedestrians->SetColorModeToColorByScalar(); extern_glyphs_pedestrians->SetScaleModeToDataScalingOff(); @@ -459,6 +474,7 @@ void ThreadVisualisation::initGlyphs(){ lut->SetHueRange(0.0,0.470); //lut->SetSaturationRange(0,0); lut->SetValueRange(1.0,1.0); + lut->SetNanColor(0.2,0.2,0.2,0.5); lut->SetNumberOfTableValues(256); lut->Build(); mapper->SetLookupTable(lut); diff --git a/src/ThreadVisualisation.h b/src/ThreadVisualisation.h index 5bed3979987093bc2fc403f1f27fcb14c911246a..37f326429936ac8ccf2628116d37f9adc3f0956c 100644 --- a/src/ThreadVisualisation.h +++ b/src/ThreadVisualisation.h @@ -38,6 +38,7 @@ #include <QThread> #include <QObject> #include <vtkGlyph3D.h> +#include <vtkTensorGlyph.h> #include <vtkSmartPointer.h> #include <vtkPolyDataMapper.h> @@ -64,6 +65,7 @@ extern Pedestrian** extern_pedestrians_secondSet; extern Pedestrian** extern_pedestrians_thirdSet; extern vtkSmartPointer<vtkGlyph3D> extern_glyphs_pedestrians; +//extern vtkSmartPointer<vtkTensorGlyph> extern_glyphs_pedestrians; extern SyncData extern_trajectories_firstSet; extern SyncData extern_trajectories_secondSet; diff --git a/src/TimerCallback.cpp b/src/TimerCallback.cpp index 306a5a669698ff6223070850df8975790a98c7ef..4c5b7cdd9bda3e1b6b0437a37969c3448fe5c296 100644 --- a/src/TimerCallback.cpp +++ b/src/TimerCallback.cpp @@ -341,10 +341,14 @@ void TimerCallback::Execute(vtkObject *caller, unsigned long eventId, pAVIWriter->SetFileName(videoName.toStdString().c_str()); if(windowToImageFilter!=NULL) - if(windowToImageFilter->GetInput()==NULL){ //should be the case by first call - windowToImageFilter->SetInput(renderWindow); - pAVIWriter->SetInput(windowToImageFilter->GetOutput()); - pAVIWriter->Start(); + if(windowToImageFilter->GetInput()==NULL){ //should be the case by first call + windowToImageFilter->SetInput(renderWindow); +#if VTK_MAJOR_VERSION <= 5 + pAVIWriter->SetInput(windowToImageFilter->GetOutput()); +#else + pAVIWriter->SetInputConnection(windowToImageFilter->GetOutputPort()); +#endif + pAVIWriter->Start(); } extern_recording_enable=true; isRecording=true; diff --git a/src/extern_var.h b/src/extern_var.h index 8fa0ee21789959dd024511493122196a9ee4674a..0d89eeb03cf0ec52860fa5302ccca28d9e45d0b5 100644 --- a/src/extern_var.h +++ b/src/extern_var.h @@ -34,6 +34,7 @@ #include "Pedestrian.h" #include <vtkGlyph3D.h> +#include <vtkTensorGlyph.h> #include <vtkSmartPointer.h> #include <vtkPolyDataMapper.h> @@ -81,6 +82,7 @@ Pedestrian** extern_pedestrians_thirdSet=NULL; VTK_CREATE (vtkGlyph3D, extern_glyphs_pedestrians); +//VTK_CREATE (vtkTensorGlyph, extern_glyphs_pedestrians); // and here the corresponding dataset diff --git a/src/general/Macros.h b/src/general/Macros.h new file mode 100644 index 0000000000000000000000000000000000000000..c0620a554d3b357daefd057e2183991d4f0dde6d --- /dev/null +++ b/src/general/Macros.h @@ -0,0 +1,109 @@ +/** + * File: Macros.h + * + * Created on 16. Juni 2010, 16:59 + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + */ + +#ifndef _MACROS_H +#define _MACROS_H + +#include <cstdlib> +#include <vector> +#include <string.h> + +//#define _SIMULATOR 1 + +#ifdef _NDEBUG +//#undef _OPENMP +#endif + +// precision error +#define J_EPS 0.001 +#define J_EPS_DIST 0.05// [m] +#define J_EPS_INFO_DIST 2.0 // [m] abstand für Informationsaustausch (GraphRouter) +#define J_EPS_GOAL 0.005 // [m] Abstand zum Ziel, damit Fußgänger immer zu einem Raum gehört +#define J_TOLERANZ 0.03 // [m] Toleranz beim erstellen der Linien +#define J_EPS_V 0.1 // [m/s] wenn v<EPS_V wird mit 0 gerechnet + + +#define JPS_VERSION "0.5" +#define JPS_VERSION_MINOR 5 +#define JPS_VERSION_MAJOR 0 + +// Länge von char vectoren zur Ausgabe +#define CLENGTH 1000 + + +// Faktor für TraVisTo (cm <-> m) +#define FAKTOR 100 + + +// final destinations for the pedestrians +#define FINAL_DEST_OUT -1 //default + + +//routing +#define J_EPS_HL_DIST 0.012 +#define J_EPS_AP_DIST J_EPS_GOAL+J_EPS_HL_DIST + +// Linked cells +#define LIST_EMPTY -1 + + +enum RoomState { + ROOM_CLEAN=0, + ROOM_SMOKED=1, +}; + +enum FileFormat { + 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_UNDEFINED =-1 +}; + + +//global functions for convenience + +inline char xmltob(const char * t,char v=0){ if (t&&(*t)) return (char)atoi(t); return v; } +inline int xmltoi(const char * t,int v=0){ if (t&&(*t)) return atoi(t); return v; } +inline long xmltol(const char * t,long v=0){ if (t&&(*t)) return atol(t); return v; } +inline double xmltof(const char * t,double v=0.0){ if (t&&(*t)) return atof(t); return v; } +inline const char * xmltoa(const char * t, const char * v=""){ if (t) return t; return v; } +inline char xmltoc(const char * t,const char v='\0'){ if (t&&(*t)) return *t; return v; } + +#endif /* _MACROS_H */ + diff --git a/src/geometry/Building.cpp b/src/geometry/Building.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5fcc440f7324f8bbcb8e066fbbd0ff0805a75c85 --- /dev/null +++ b/src/geometry/Building.cpp @@ -0,0 +1,1484 @@ +/** + * File: Building.cpp + * + * Created on 1. October 2010, 09:25 + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#include "Building.h" +#include "../tinyxml/tinyxml.h" + +#ifdef _SIMULATOR +#include "../pedestrian/Pedestrian.h" +#include "../mpi/LCGrid.h" +#include "../routing/RoutingEngine.h" +#endif + +//#undef _OPENMP + +#ifdef _OPENMP +#include <omp.h> +#else +#define omp_get_thread_num() 0 +#define omp_get_max_threads() 1 +#endif + +OutputHandler* Log = new STDIOHandler();; + +using namespace std; + +/************************************************************ + Konstruktoren + ************************************************************/ + +Building::Building() { + _caption = "no_caption"; + _projectFilename = ""; + _rooms = vector<Room*>(); + _routingEngine = NULL; + _linkedCellGrid = NULL; + _savePathway = false; +} + + +Building::~Building() { + for (int i = 0; i < GetNumberOfRooms(); i++) + delete _rooms[i]; + +#ifdef _SIMULATOR + 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; + } +} + +/************************************************************ + Setter-Funktionen + ************************************************************/ +void Building::SetCaption(const std::string& s) { + _caption = s; +} + +void Building::SetRoutingEngine(RoutingEngine* r) { + _routingEngine = r; +} + +void Building::SetRoom(Room* room, int index) { + if ((index >= 0) && (index < (int) _rooms.size())) { + _rooms[index] = room; + } else { + Log->Write("ERROR: \tWrong Index in CBuilding::SetRoom()"); + exit(0); + } +} + +/************************************************************* + Getter-Funktionen + ************************************************************/ + +string Building::GetCaption() const { + return _caption; +} + +RoutingEngine* Building::GetRoutingEngine() const { + return _routingEngine; +} + +int Building::GetNumberOfRooms() const { + return _rooms.size(); +} + +int Building::GetNumberOfGoals() const { + return _transitions.size() + _hLines.size() + _crossings.size(); +} + +const vector<Room*>& Building::GetAllRooms() const { + return _rooms; +} + +Room* Building::GetRoom(int index) const { + if ((index >= 0) && (index < (int) _rooms.size())) { + return _rooms[index]; + } else { + char tmp[CLENGTH]; + sprintf(tmp, + "ERROR: Wrong 'index' in CBuiling::GetRoom() index: %d size: %d", + index, _rooms.size()); + Log->Write(tmp); + exit(0); + } +} + + + +LCGrid* Building::GetGrid() const { + return _linkedCellGrid; +} + +void Building::AddRoom(Room* room) { + _rooms.push_back(room); +} + +void Building::AddSurroundingRoom() { + Log->Write("INFO: \tAdding the room 'outside' "); + // first look for the geometry boundaries + double x_min = FLT_MAX; + double x_max = -FLT_MAX; + double y_min = FLT_MAX; + double y_max = -FLT_MAX; + //finding the bounding of the grid + // and collect the pedestrians + for (unsigned int r = 0; r < _rooms.size(); r++) { + Room* room = _rooms[r]; + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + const vector<Wall>& allWalls = sub->GetAllWalls(); + + for (unsigned int a = 0; a < allWalls.size(); a++) { + double x1 = allWalls[a].GetPoint1().GetX(); + double y1 = allWalls[a].GetPoint1().GetY(); + double x2 = allWalls[a].GetPoint2().GetX(); + double y2 = allWalls[a].GetPoint2().GetY(); + + double xmax = (x1 > x2) ? x1 : x2; + double xmin = (x1 > x2) ? x2 : x1; + double ymax = (y1 > y2) ? y1 : y2; + double ymin = (y1 > y2) ? y2 : y1; + + x_min = (xmin <= x_min) ? xmin : x_min; + x_max = (xmax >= x_max) ? xmax : x_max; + y_max = (ymax >= y_max) ? ymax : y_max; + y_min = (ymin <= y_min) ? ymin : y_min; + } + } + } + + for (map<int, Goal*>::const_iterator itr = _goals.begin(); + itr != _goals.end(); ++itr) { + + const vector<Wall>& allWalls = itr->second->GetAllWalls(); + + for (unsigned int a = 0; a < allWalls.size(); a++) { + double x1 = allWalls[a].GetPoint1().GetX(); + double y1 = allWalls[a].GetPoint1().GetY(); + double x2 = allWalls[a].GetPoint2().GetX(); + double y2 = allWalls[a].GetPoint2().GetY(); + + double xmax = (x1 > x2) ? x1 : x2; + double xmin = (x1 > x2) ? x2 : x1; + double ymax = (y1 > y2) ? y1 : y2; + double ymin = (y1 > y2) ? y2 : y1; + + x_min = (xmin <= x_min) ? xmin : x_min; + x_max = (xmax >= x_max) ? xmax : x_max; + y_max = (ymax >= y_max) ? ymax : y_max; + y_min = (ymin <= y_min) ? ymin : y_min; + } + } + + //make the grid slightly larger. + x_min = x_min - 10.0; + x_max = x_max + 10.0; + y_min = y_min - 10.0; + y_max = y_max + 10.0; + + SubRoom* bigSubroom = new NormalSubRoom(); + bigSubroom->SetRoomID(_rooms.size()); + bigSubroom->SetSubRoomID(0); // should be the single subroom + bigSubroom->AddWall(Wall(Point(x_min, y_min), Point(x_min, y_max))); + bigSubroom->AddWall(Wall(Point(x_min, y_max), Point(x_max, y_max))); + bigSubroom->AddWall(Wall(Point(x_max, y_max), Point(x_max, y_min))); + bigSubroom->AddWall(Wall(Point(x_max, y_min), Point(x_min, y_min))); + + Room * bigRoom = new Room(); + bigRoom->AddSubRoom(bigSubroom); + bigRoom->SetCaption("outside"); + bigRoom->SetID(_rooms.size()); + AddRoom(bigRoom); +} + + +void Building::InitGeometry() { + Log->Write("INFO: \tInit Geometry"); + for (int i = 0; i < GetNumberOfRooms(); i++) { + Room* room = GetRoom(i); + // Polygone berechnen + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* s = room->GetSubRoom(j); + // Alle Übergänge in diesem Raum bestimmen + // Übergänge müssen zu Wänden ergänzt werden + vector<Line*> goals = vector<Line*>(); + + // crossings + const vector<Crossing*>& crossings = s->GetAllCrossings(); + for (unsigned int i = 0; i < crossings.size(); i++) { + goals.push_back(crossings[i]); + } + + // and transitions + const vector<Transition*>& transitions = s->GetAllTransitions(); + for (unsigned int i = 0; i < transitions.size(); i++) { + goals.push_back(transitions[i]); + } + + // initialize the poly + s->ConvertLineToPoly(goals); + s->CalculateArea(); + goals.clear(); + + //do the same for the obstacles that are closed + const vector<Obstacle*>& obstacles = s->GetAllObstacles(); + for (unsigned int obs = 0; obs < obstacles.size(); ++obs) { + if (obstacles[obs]->GetClosed() == 1) + obstacles[obs]->ConvertLineToPoly(); + } + } + } + Log->Write("INFO: \tInit Geometry successful!!!\n"); +} + + + + +const string& Building::GetProjectFilename() const{ + return _projectFilename; +} + +void Building::SetProjectFilename(const std::string &filename){ + _projectFilename=filename; +} + +void Building::SetProjectRootDir(const std::string &filename){ + _projectRootDir= filename; +} + +const string& Building::GetProjectRootDir() const{ + return _projectRootDir; +} + + +void Building::LoadBuildingFromFile(const std::string &filename) { + + //get the geometry filename from the project file if none was supplied + string geoFilename=filename; + if(geoFilename==""){ + 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(); + if(xMainNode->FirstChild("geometry")){ + geoFilename=_projectRootDir+xMainNode->FirstChild("geometry")->FirstChild()->Value(); + Log->Write("INFO: \tgeometry <"+geoFilename+">"); + } + } else { + geoFilename=_projectRootDir+geoFilename; + } + + TiXmlDocument docGeo(geoFilename); + 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.4) { + Log->Write("ERROR: \tOnly version > 0.4 supported"); + Log->Write("ERROR: \tparsing geometry file failed!"); + 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]; + 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"); +} + +Room* Building::GetRoom(string caption) const { + for (unsigned int r = 0; r < _rooms.size(); r++) { + if (_rooms[r]->GetCaption() == caption) + return _rooms[r]; + } + Log->Write("Warning: Room not found with caption " + caption); + //return NULL; + exit(EXIT_FAILURE); +} + +void Building::AddCrossing(Crossing* line) { + if (_crossings.count(line->GetID()) != 0) { + char tmp[CLENGTH]; + sprintf(tmp, + "ERROR: Duplicate index for crossing found [%d] in Routing::AddCrossing()", + line->GetID()); + Log->Write(tmp); + exit(EXIT_FAILURE); + } + _crossings[line->GetID()] = line; +} + +void Building::AddTransition(Transition* line) { + if (_transitions.count(line->GetID()) != 0) { + char tmp[CLENGTH]; + sprintf(tmp, + "ERROR: Duplicate index for transition found [%d] in Routing::AddTransition()", + line->GetID()); + Log->Write(tmp); + exit(EXIT_FAILURE); + } + _transitions[line->GetID()] = line; +} + +void Building::AddHline(Hline* line) { + if (_hLines.count(line->GetID()) != 0) { + Log->Write( + "ERROR: Duplicate index for hlines found [%d] in Routing::AddHline()", + line->GetID()); + 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; +} + +const map<int, Crossing*>& Building::GetAllCrossings() const { + return _crossings; +} + +const map<int, Transition*>& Building::GetAllTransitions() const { + return _transitions; +} + +const map<int, Hline*>& Building::GetAllHlines() const { + return _hLines; +} + +const map<int, Goal*>& Building::GetAllGoals() const { + return _goals; +} + +Transition* Building::GetTransition(string caption) const { + //eventually + map<int, Transition*>::const_iterator itr; + for(itr = _transitions.begin(); itr != _transitions.end(); ++itr){ + if (itr->second->GetCaption() == caption) + return itr->second; + } + + Log->Write("WARNING: No Transition with Caption: " + caption); + exit(EXIT_FAILURE); +} + +Transition* Building::GetTransition(int ID) { + if (_transitions.count(ID) == 1) { + return _transitions[ID]; + } else { + if (ID == -1) + return NULL; + else { + Log->Write( + "ERROR: I could not find any transition with the 'ID' [%d]. You have defined [%d] transitions", + ID, _transitions.size()); + exit(EXIT_FAILURE); + } + } +} + +Goal* Building::GetFinalGoal(int ID) { + if (_goals.count(ID) == 1) { + return _goals[ID]; + } else { + if (ID == -1) + return NULL; + else { + Log->Write( + "ERROR: I could not find any goal with the 'ID' [%d]. You have defined [%d] goals", + ID, _goals.size()); + exit(EXIT_FAILURE); + } + } +} + +Crossing* Building::GetTransOrCrossByName(string caption) const { + + { + //eventually + map<int, Transition*>::const_iterator itr; + for(itr = _transitions.begin(); itr != _transitions.end(); ++itr){ + if (itr->second->GetCaption() == caption) + return itr->second; + } + } + { + //finally the crossings + map<int, Crossing*>::const_iterator itr; + for(itr = _crossings.begin(); itr != _crossings.end(); ++itr){ + if (itr->second->GetCaption() == caption) + return itr->second; + } + } + + Log->Write("WARNING: No Transition or Crossing with Caption: " + caption); + return NULL; +} + +Crossing* Building::GetTransOrCrossByID(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; +} + + +bool Building::IsVisible(Line* l1, Line* l2, bool considerHlines){ + for (unsigned int i = 0; i < _rooms.size();i++) { + Room* room = _rooms[i]; + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + if(sub->IsVisible(l1,l2,considerHlines)==false) return false; + } + } + return true; +} + +bool Building::IsVisible(const Point& p1, const Point& p2, bool considerHlines){ + for (unsigned int i = 0; i < _rooms.size();i++) { + Room* room = _rooms[i]; + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + if(sub->IsVisible(p1,p2,considerHlines)==false) return false; + } + } + return true; +} + +void Building::SanityCheck(){ + Log->Write("INFO: \tChecking the geometry for artifacts"); + for (unsigned int i = 0; i < _rooms.size();i++) { + Room* room = _rooms[i]; + + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + sub->SanityCheck(); + } + } + Log->Write("INFO: \t...Done!!!\n"); +} + +#ifdef _SIMULATOR + +//TODO: merge this with Update and improve runtime +void Building::UpdateVerySlow(){ + + vector<Pedestrian*> nonConformPeds; + for (int i = 0; i < GetNumberOfRooms(); i++) { + Room* room = GetRoom(i); + + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + for (int k = 0; k < sub->GetNumberOfPedestrians(); k++) { + Pedestrian* ped = sub->GetPedestrian(k); + //set the new room if needed + if ((ped->GetFinalDestination() == FINAL_DEST_OUT) + && (GetRoom(ped->GetRoomID())->GetCaption() == "outside")) { + + sub->DeletePedestrian(k--); + DeletePedestrian(ped); + } else if ((ped->GetFinalDestination() != FINAL_DEST_OUT) + && (_goals[ped->GetFinalDestination()]->Contains( + ped->GetPos()))) { + sub->DeletePedestrian(k--); + DeletePedestrian(ped); + } else if (!sub->IsInSubRoom(ped)) { + nonConformPeds.push_back(ped); + sub->DeletePedestrian(k--); + } + } + } + } + + // reset that pedestrians who left their room not via the intended exit + for (int p = 0; p < (int) nonConformPeds.size(); p++) { + Pedestrian* ped = nonConformPeds[p]; + bool assigned = false; + for (int i = 0; i < GetNumberOfRooms(); i++) { + Room* room = GetRoom(i); + //if(room->GetCaption()=="outside") continue; + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + SubRoom* old_sub= _rooms[ped->GetRoomID()]->GetSubRoom(ped->GetSubRoomID()); + if ((sub->IsInSubRoom(ped->GetPos())) && (sub->IsDirectlyConnectedWith(old_sub))) { + ped->SetRoomID(room->GetID(), room->GetCaption()); + ped->SetSubRoomID(sub->GetSubRoomID()); + ped->ClearMentalMap(); // reset the destination + //ped->FindRoute(); + sub->AddPedestrian(ped); + assigned = true; + break; + } + } + if (assigned == true) + break; // stop the loop + } + if (assigned == false) { + DeletePedestrian(ped); + } + } + + // find the new goals, the parallel way + + unsigned int nSize = _allPedestians.size(); + int nThreads = omp_get_max_threads(); + + // check if worth sharing the work + if (nSize < 12) + nThreads = 1; + + int partSize = nSize / nThreads; + +#pragma omp parallel default(shared) num_threads(nThreads) + { + const int threadID = omp_get_thread_num(); + int start = threadID * partSize; + int end = (threadID + 1) * partSize - 1; + if ((threadID == nThreads - 1)) + end = nSize - 1; + + for (int p = start; p <= end; ++p) { + if (_allPedestians[p]->FindRoute() == -1) { + //a destination could not be found for that pedestrian + //Log->Write("\tINFO: \tCould not found a route for pedestrian %d",_allPedestians[p]->GetID()); + //Log->Write("\tINFO: \tHe has reached the target cell"); + DeletePedFromSim(_allPedestians[p]); + //exit(EXIT_FAILURE); + } + } + } +} + +void Building::Update() { + // some peds may change the room via another crossing than the primary intended one + // in that case they are set in the wrong room. + vector<Pedestrian*> nonConformPeds; + for (int i = 0; i < GetNumberOfRooms(); i++) { + Room* room = GetRoom(i); + + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + for (int k = 0; k < sub->GetNumberOfPedestrians(); k++) { + Pedestrian* ped = sub->GetPedestrian(k); + //set the new room if needed + if (!sub->IsInSubRoom(ped)) { + // the peds has changed the room and is farther than 50 cm from + // the exit, thats a real problem. + if (ped->GetExitLine()->DistTo(ped->GetPos()) > 0.50) { + Log->Write( + "WARNING: Building::update() pedestrian [%d] left the room/subroom [%s][%d/%d] " + "via unknown exit[??%d] \n Position: (%f, %f), distance to exit: (%f)", + ped->GetID(), + _rooms[ped->GetRoomID()]->GetCaption().c_str(), + ped->GetRoomID(), ped->GetSubRoomID(), + ped->GetExitIndex(), ped->GetPos().GetX(), + ped->GetPos().GetY(),ped->GetExitLine()->DistTo(ped->GetPos())); + //ped->Dump(ped->GetPedIndex()); + //std::cout << ped->GetLastDestination() << " " + // << ped->GetNextDestination() << std::endl; + //exit(0); + nonConformPeds.push_back(ped); + sub->DeletePedestrian(k--); + continue; // next pedestrian + } + + //safely converting (upcasting) the NavLine to a crossing. + Crossing* cross = + dynamic_cast<Crossing*>(ped->GetExitLine()); + if (cross == NULL) { + Log->Write("ERROR: Building::update() type casting error for ped %d",ped->GetID()); + Log->Write("ERROR: Fix Me !"); + nonConformPeds.push_back(ped); + exit(EXIT_FAILURE); + continue; + //fixme all portal should be derived from crossings + } + + SubRoom* other_sub = cross->GetOtherSubRoom( + room->GetID(), j); + + if (other_sub) { + int nextSubRoom = other_sub->GetSubRoomID(); + int nextRoom = other_sub->GetRoomID(); + ped->SetSubRoomID(nextSubRoom); + ped->SetRoomID(nextRoom, + GetRoom(nextRoom)->GetCaption()); + other_sub->AddPedestrian(ped); + + } else { + DeletePedestrian(ped); + //continue; + } + // Lösche Fußgänger aus aktuellem SubRoom + sub->DeletePedestrian(k--); // k--; + } + // neues Ziel setzten + //pRouting->FindExit(ped); + } + } + } + + // reset that pedestrians who left their room not via the intended exit + for (int p = 0; p < (int) nonConformPeds.size(); p++) { + Pedestrian* ped = nonConformPeds[p]; + bool assigned = false; + for (int i = 0; i < GetNumberOfRooms(); i++) { + Room* room = GetRoom(i); + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + //only relocate in the same room + // or only in neighbouring rooms + if (room->GetID() != ped->GetRoomID()) + continue; + if (sub->IsInSubRoom(ped->GetPos())) { + //set in the new room + Log->Write("pedestrian %d relocated from room/subroom [%s] %d/%d to [%s] %d/%d ", + ped->GetID(), + GetRoom(ped->GetRoomID())->GetCaption().c_str(), + ped->GetRoomID(), ped->GetSubRoomID(), + room->GetCaption().c_str(), i, j); + ped->SetRoomID(room->GetID(), room->GetCaption()); + ped->SetSubRoomID(sub->GetSubRoomID()); + ped->ClearMentalMap(); // reset the destination + ped->FindRoute(); + sub->AddPedestrian(ped); + assigned = true; + break; + } + } + if (assigned == true) + break; // stop the loop + } + if (assigned == false) { + DeletePedestrian(ped); + } + } + + // find the new goals, the parallel way + + unsigned int nSize = _allPedestians.size(); + int nThreads = omp_get_max_threads(); + + // check if worth sharing the work + if (nSize < 12) + nThreads = 1; + + int partSize = nSize / nThreads; + +#pragma omp parallel default(shared) num_threads(nThreads) + { + const int threadID = omp_get_thread_num(); + int start = threadID * partSize; + int end = (threadID + 1) * partSize - 1; + if ((threadID == nThreads - 1)) + end = nSize - 1; + + for (int p = start; p <= end; ++p) { + if (_allPedestians[p]->FindRoute() == -1) { + //a destination could not be found for that pedestrian + //Log->Write("\tINFO: \tCould not found a route for pedestrian %d",_allPedestians[p]->GetID()); + //Log->Write("\tINFO: \tHe has reached the target cell"); + DeletePedFromSim(_allPedestians[p]); + //exit(EXIT_FAILURE); + } + } + } + + //cleaning up + //CleanUpTheScene(); +} + + +void Building::InitPhiAllPeds(double pDt) { + for (int i = 0; i < GetNumberOfRooms(); i++) { + Room* room = GetRoom(i); + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + for (int k = 0; k < sub->GetNumberOfPedestrians(); k++) { + double cosPhi, sinPhi; + Pedestrian* ped = sub->GetPedestrian(k); + ped->Setdt(pDt); //set the simulation step + ped->SetRoomID(room->GetID(), room->GetCaption()); + //a destination could not be found for that pedestrian + if (ped->FindRoute() == -1) { + // DeletePedFromSim(ped); + sub->DeletePedestrian(k--); + continue; + } + Line* e = ped->GetExitLine(); + const Point& e1 = e->GetPoint1(); + const Point& e2 = e->GetPoint2(); + Point target = (e1 + e2) * 0.5; + Point d = target - ped->GetPos(); + double dist = d.Norm(); + if (dist != 0.0) { + cosPhi = d.GetX() / dist; + sinPhi = d.GetY() / dist; + } else { + Log->Write( + "ERROR: \tBuilding::InitPhiAllPeds() cannot initialise phi! " + "dist to target ist 0\n"); + exit(0); + } + + JEllipse E = ped->GetEllipse(); + E.SetCosPhi(cosPhi); + E.SetSinPhi(sinPhi); + ped->SetEllipse(E); + } + } + } +} + +void Building::UpdateGrid() { + _linkedCellGrid->Update(_allPedestians); +} + +void Building::InitGrid(double cellSize) { + + // first look for the geometry boundaries + double x_min = FLT_MAX; + double x_max = FLT_MIN; + double y_min = FLT_MAX; + double y_max = FLT_MIN; + + //finding the bounding of the grid + // and collect the pedestrians + for (unsigned int r = 0; r < _rooms.size(); r++) { + Room* room = _rooms[r]; + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + const vector<Wall>& allWalls = sub->GetAllWalls(); + + for (unsigned int a = 0; a < allWalls.size(); a++) { + double x1 = allWalls[a].GetPoint1().GetX(); + double y1 = allWalls[a].GetPoint1().GetY(); + double x2 = allWalls[a].GetPoint2().GetX(); + double y2 = allWalls[a].GetPoint2().GetY(); + + double xmax = (x1 > x2) ? x1 : x2; + double xmin = (x1 > x2) ? x2 : x1; + double ymax = (y1 > y2) ? y1 : y2; + double ymin = (y1 > y2) ? y2 : y1; + + x_min = (xmin <= x_min) ? xmin : x_min; + x_max = (xmax >= x_max) ? xmax : x_max; + y_max = (ymax >= y_max) ? ymax : y_max; + y_min = (ymin <= y_min) ? ymin : y_min; + } + } + } + + for (unsigned int wa = 0; wa < _rooms.size(); wa++) { + Room* room = _rooms[wa]; + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + for (int k = 0; k < sub->GetNumberOfPedestrians(); k++) { + Pedestrian* ped = sub->GetPedestrian(k); + _allPedestians.push_back(ped); + } + } + } + + //make the grid slightly larger. + x_min = x_min - 1.0; + x_max = x_max + 1.0; + y_min = y_min - 1.0; + y_max = y_max + 1.0; + + double boundaries[] = { x_min, x_max, y_min, y_max }; + int pedsCount = _allPedestians.size(); + + //no algorithms + // the domain is made of a sigle cell + if(cellSize==-1){ + Log->Write("INFO: \tBrute Force will be used for neighborhoods query"); + if ( (x_max-x_min) < (y_max-y_min) ){ + cellSize=(y_max-y_min); + }else { + cellSize=(x_max-x_min); + } + + }else{ + Log->Write("INFO: \tInitializing the grid with cell size: %f ", cellSize); + } + + _linkedCellGrid = new LCGrid(boundaries, cellSize, pedsCount); + _linkedCellGrid->ShallowCopy(_allPedestians); + + Log->Write("INFO: \tDone with Initializing the grid "); +} + + + +void Building::DumpSubRoomInRoom(int roomID, int subID) { + SubRoom* sub = GetRoom(roomID)->GetSubRoom(subID); + if (sub->GetNumberOfPedestrians() == 0) + return; + cout << "dumping room/subroom " << roomID << " / " << subID << endl; + for (int p = 0; p < sub->GetNumberOfPedestrians(); p++) { + Pedestrian* ped = sub->GetPedestrian(p); + cout << " ID: " << ped->GetID(); + cout << " Index: " << p << endl; + } + +} + + +void Building::LoadRoutingInfo(const string &filename) { + + + Log->Write("INFO:\tLoading extra routing information"); + if (filename == "") { + Log->Write("INFO:\t No file supplied !"); + Log->Write("INFO:\t done with loading extra routing information"); + return; + } + TiXmlDocument docRouting(filename); + if (!docRouting.LoadFile()){ + Log->Write("ERROR: \t%s", docRouting.ErrorDesc()); + Log->Write("ERROR: \t could not parse the routing file"); + exit(EXIT_FAILURE); + } + + TiXmlElement* xRootNode = docRouting.RootElement(); + if( ! xRootNode ) { + Log->Write("ERROR:\tRoot element does not exist"); + exit(EXIT_FAILURE); + } + + //load goals and routes + TiXmlNode* xGoalsNode = xRootNode->FirstChild("routing")->FirstChild("goals"); + + + if(xGoalsNode) + for(TiXmlElement* e = xGoalsNode->FirstChildElement("goal"); e; + e = e->NextSiblingElement("goal")) { + + int id = xmltof(e->Attribute("id"), -1); + int isFinal= string(e->Attribute("final"))=="true"?true:false; + string caption = xmltoa(e->Attribute("caption"),"-1"); + + Goal* goal = new Goal(); + goal->SetId(id); + goal->SetCaption(caption); + goal->SetIsFinalGoal(isFinal); + + //looking for polygons (walls) + for(TiXmlElement* xPolyVertices = e->FirstChildElement("polygon"); xPolyVertices; + xPolyVertices = xPolyVertices->NextSiblingElement("polygon")) { + + for (TiXmlElement* xVertex = xPolyVertices->FirstChildElement( + "vertex"); + xVertex && xVertex != xPolyVertices->LastChild("vertex"); + xVertex = xVertex->NextSiblingElement("vertex")) { + + double x1 = xmltof(xVertex->Attribute("px")); + double y1 = xmltof(xVertex->Attribute("py")); + double x2 = xmltof(xVertex->NextSiblingElement("vertex")->Attribute("px")); + double y2 = xmltof(xVertex->NextSiblingElement("vertex")->Attribute("py")); + goal->AddWall(Wall(Point(x1, y1), Point(x2, y2))); + } + } + + goal->ConvertLineToPoly(); + AddGoal(goal); + _routingEngine->AddFinalDestinationID(goal->GetId()); + } + + //load routes + TiXmlNode* xTripsNode = xRootNode->FirstChild("routing")->FirstChild("routes"); + + if(xTripsNode) + for(TiXmlElement* trip = xTripsNode->FirstChildElement("route"); trip; + trip = trip->NextSiblingElement("route")) { + + double id = xmltof(trip->Attribute("id"), -1); + if (id == -1) { + Log->Write("ERROR:\t id missing for trip"); + exit(EXIT_FAILURE); + } + string sTrip = trip->FirstChild()->ValueStr(); + vector<string> vTrip; + vTrip.clear(); + + char* str = (char*) sTrip.c_str(); + char *p = strtok(str, ":"); + while (p) { + vTrip.push_back(xmltoa(p)); + p = strtok(NULL, ":"); + } + _routingEngine->AddTrip(vTrip); + } + Log->Write("INFO:\tdone with loading extra routing information"); +} + +void Building::LoadTrafficInfo() { + + Log->Write("INFO:\tLoading the traffic info file"); + + string trafficFile=""; + TiXmlDocument doc(_projectFilename); + if (!doc.LoadFile()){ + Log->Write("ERROR: \t%s", doc.ErrorDesc()); + Log->Write("ERROR: \t could not parse the project file"); + exit(EXIT_FAILURE); + } + + TiXmlNode* xRootNode = doc.RootElement()->FirstChild("traffic_constraints"); + if( ! xRootNode ) { + Log->Write("WARNING:\tcould not find any traffic information"); + return; + //exit(EXIT_FAILURE); + } + + //processing the rooms node + TiXmlNode* xRoomsNode = xRootNode->FirstChild("rooms"); + if(xRoomsNode) + for(TiXmlElement* xRoom = xRoomsNode->FirstChildElement("room"); xRoom; + xRoom = xRoom->NextSiblingElement("room")) { + + double id = xmltof(xRoom->Attribute("room_id"), -1); + string state = xmltoa(xRoom->Attribute("state"), "good"); + RoomState status = (state == "good") ? ROOM_CLEAN : ROOM_SMOKED; + _rooms[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); + } + 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; + } + } +} + +const vector<Pedestrian*>& Building::GetAllPedestrians() const { + return _allPedestians; +} + +void Building::AddPedestrian(Pedestrian* ped) { + + // for(unsigned int p = 0;p<pAllPedestians.size();p++){ + // Pedestrian* ped1=pAllPedestians[p]; + // if(ped->GetPedIndex()==ped1->GetPedIndex()){ + // cout<<"Pedestrian already in the room ??? "<<ped->GetPedIndex()<<endl; + // return; + // } + // } + _allPedestians.push_back(ped); +} + + +//obsolete +void Building::InitSavePedPathway(const string &filename) { + _pathWayStream.open(filename.c_str()); + _savePathway = true; + + if (_pathWayStream.is_open()) { + Log->Write("#INFO:\tsaving pedestrian paths to [ " + filename + " ]"); + _pathWayStream << "##pedestrian ways" << endl; + _pathWayStream << "#nomenclature roomid caption" << endl; + // for (unsigned int r=0;r< pRooms.size();r++){ + // Room* room= GetRoom(r); + // const vector<int>& goals=room->GetAllTransitionsIDs(); + // + // for(unsigned int g=0;g<goals.size();g++){ + // int exitid=goals[g]; + // string exit_caption=pRouting->GetGoal(exitid)->GetCaption(); + // PpathWayStream<<exitid<<" "<<exit_caption<<endl; + // } + // } + // + _pathWayStream << "#data room exit_id" << endl; + } else { + Log->Write("#INFO:\t Unable to open [ " + filename + " ]"); + Log->Write("#INFO:\t saving to stdout"); + + } +} + +void Building::CleanUpTheScene() { + //return; + static int counter = 0; + counter++; + static int totalSliced = 0; + + int updateRate = 80.0 / 0.01; // 20 seconds/pDt + + if (counter % updateRate == 0) { + for (unsigned int i = 0; i < _allPedestians.size(); i++) { + Pedestrian* ped = _allPedestians[i]; + + if (ped->GetDistanceSinceLastRecord() < 0.1) { + //delete from the simulation + DeletePedFromSim(ped); + + totalSliced++; + char msg[CLENGTH]; + sprintf(msg, "INFO:\t slicing Ped %d from room %s, total [%d]", + ped->GetID(), + _rooms[ped->GetRoomID()]->GetCaption().c_str(), + totalSliced); + Log->Write(msg); + } else { + ped->RecordActualPosition(); + } + + } + } + +} + + +void Building::StringExplode(string str, string separator, + vector<string>* results) { + size_t found; + found = str.find_first_of(separator); + while (found != string::npos) { + if (found > 0) { + results->push_back(str.substr(0, found)); + } + str = str.substr(found + 1); + found = str.find_first_of(separator); + } + if (str.length() > 0) { + results->push_back(str); + } +} + +Pedestrian* Building::GetPedestrian(int pedID) const { + for (unsigned int i = 0; i < _rooms.size(); i++) { + Room* room = _rooms[i]; + for (int j = 0; j < room->GetNumberOfSubRooms(); j++) { + SubRoom* sub = room->GetSubRoom(j); + for (int k = 0; k < sub->GetNumberOfPedestrians(); k++) { + Pedestrian* p = sub->GetPedestrian(k); + if (p->GetID() == pedID) { + return p; + } + } + } + } + return NULL; +} + +int Building::GetNumberOfPedestrians() const { + int sum = 0; + for (unsigned int wa = 0; wa < _rooms.size(); wa++) { + sum += _rooms[wa]->GetNumberOfPedestrians(); + } + return sum; +} + +// FIXME: you should get rid of this method +//Crossing* Building::GetGoal(int index) { +// if (_transitions.count(index) == 1) { +// return _transitions[index]; +// } else if (_crossings.count(index) == 1) { +// return _crossings[index]; +// }else if (_hLines.count(index) == 1) { +// exit(EXIT_FAILURE); +// //return pHlines[index]; +// }else { +// if (index == -1) +// return NULL; +// else { +// char tmp[CLENGTH]; +// sprintf(tmp, +// "ERROR: Wrong 'index' [%d] > [%d] in Routing::GetGoal(), counts in map= [%d]", +// index, _crossings.size(),_crossings.count(index)); +// Log->Write(tmp); +// exit(EXIT_FAILURE); +// } +// } +//} + + +#endif // _SIMULATOR diff --git a/src/geometry/Building.h b/src/geometry/Building.h new file mode 100644 index 0000000000000000000000000000000000000000..ba40c002407cf850e8e6bc4ad3ededc1080b6e58 --- /dev/null +++ b/src/geometry/Building.h @@ -0,0 +1,197 @@ +/** + * File: Building.h + * + * + * Created on 1. October 2010, 09:25 + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#ifndef _BUILDING_H +#define _BUILDING_H + +#include <string> +#include <vector> +#include <fstream> +#include <cfloat> +#include <map> + +#include "Room.h" +#include "NavLine.h" +#include "Transition.h" +#include "Hline.h" +#include "Obstacle.h" +#include "Goal.h" + +class RoutingEngine; +class Pedestrian; +class Transition; +class LCGrid; + + +class Building { +private: + std::string _caption; + std::string _projectFilename; + std::string _projectRootDir; + 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 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 id. + * Return NULL if none is found + */ + Crossing* GetTransOrCrossByID(int id) 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; + + // Sonstiges + 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; + void SetProjectFilename(const std::string &filename) ; + void SetProjectRootDir(const std::string &filename); + void LoadBuildingFromFile(const std::string &filename=""); + 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 */ + diff --git a/src/geometry/Crossing.cpp b/src/geometry/Crossing.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d96317bd9723f61dc4a6ab05b4097b19d3b1d6b0 --- /dev/null +++ b/src/geometry/Crossing.cpp @@ -0,0 +1,175 @@ +/** + * File: Crossing.cpp + * + * + * Created on 16. November 2010, 12:56 + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + * + */ + + +#include "Crossing.h" +#include "Room.h" +#include "SubRoom.h" + +using namespace std; + + +Crossing::Crossing(){ + _id = -1; + _room1 = NULL; + _subRoom1 = NULL; + _subRoom2 = NULL; + _caption = ""; +} + +Crossing::~Crossing() { +} + + +void Crossing::SetID(int ID) { + _id = ID; +} + +void Crossing::SetRoom1(Room* r) { + _room1 = r; +} + +void Crossing::SetSubRoom1(SubRoom* r1) { + _subRoom1 = r1; +} + +void Crossing::SetSubRoom2(SubRoom* r2) { + _subRoom2 = r2; +} + +void Crossing::SetCaption(string s) { + _caption = s; +} +// Getter-Funktionen + +int Crossing::GetID() const { + return _id; +} +string Crossing::GetCaption() const { + return _caption; +} +Room* Crossing::GetRoom1() const { + return _room1; +} + + +SubRoom* Crossing::GetSubRoom1() const { + return _subRoom1; +} + +SubRoom* Crossing::GetSubRoom2() const { + return _subRoom2; +} +// Sonstiges + + +bool Crossing::IsExit() const { + return false; +} + + +bool Crossing::IsOpen() const { + return true; +} + +bool Crossing::IsTransition() const { + return false; +} + + +bool Crossing::IsInRoom(int roomID) const { + return _room1->GetID() == roomID; +} + + +bool Crossing::IsInSubRoom(int subroomID) const { + bool r1, r2; + if (_subRoom1 != NULL) + r1 = _subRoom1->GetSubRoomID() == subroomID; + else + r1 = false; + if (_subRoom2 != NULL) + r2 = _subRoom2->GetSubRoomID() == subroomID; + else + r2 = false; + return (r1 || r2); +} + +/* gibt den ANDEREN Subroom != subroomID zurück + * roomID wird hier nicht benötigt, aber in Transition::GetOtherSubRoom() + * (virtuelle Funktion) */ +SubRoom* Crossing::GetOtherSubRoom(int roomID, int subroomID) const { + if (_subRoom1->GetSubRoomID() == subroomID) + return _subRoom2; + else if (_subRoom2->GetSubRoomID() == subroomID) + return _subRoom1; + else { + Log->Write("WARMING: \tCrossing::GetOtherSubRoom No exit found " + "on the other side\n ID=%hd, roomID=%hd, subroomID=%hd\n",GetID(),roomID,subroomID); + return NULL; + } +} + + +// Ausgabe + +void Crossing::WriteToErrorLog() const { + string s; + char tmp[CLENGTH]; + sprintf(tmp, "\t\tCROSS: %d (%f, %f) -- (%f, %f)\n", GetID(), GetPoint1().GetX(), + GetPoint1().GetY(), GetPoint2().GetX(), GetPoint2().GetY()); + s.append(tmp); + sprintf(tmp, "\t\t\t\tSubRoom: %d <-> SubRoom: %d\n", GetSubRoom1()->GetSubRoomID(), + GetSubRoom2()->GetSubRoomID()); + s.append(tmp); + Log->Write(s); +} + +// TraVisTo Ausgabe + +string Crossing::WriteElement() const { + //return ""; + string geometry; + char tmp[CLENGTH] = ""; + sprintf(tmp,"\t\t<door ID=\"%d\" color = \"250\" caption=\"%d_%d\">\n",GetUniqueID(),GetID(),GetUniqueID()); + geometry.append(tmp); + //geometry.append("\t\t<door color=\"250\">\n"); + sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\" />\n", + (GetPoint1().GetX()) * FAKTOR, + (GetPoint1().GetY()) * FAKTOR, + _subRoom1->GetElevation(GetPoint1())*FAKTOR); + geometry.append(tmp); + sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\" />\n", + (GetPoint2().GetX()) * FAKTOR, + (GetPoint2().GetY()) * FAKTOR, + _subRoom1->GetElevation(GetPoint2())*FAKTOR); + geometry.append(tmp); + geometry.append("\t\t</door>\n"); + return geometry; +} diff --git a/src/geometry/Crossing.h b/src/geometry/Crossing.h new file mode 100644 index 0000000000000000000000000000000000000000..55db521010604961457bab08714e4a265a9887e8 --- /dev/null +++ b/src/geometry/Crossing.h @@ -0,0 +1,147 @@ +/** + * File: Crossing.h + * + * + * Created on 16. November 2010, 12:56 + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#ifndef _CROSSING_H +#define _CROSSING_H + +#include "NavLine.h" + +//class Line; +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; +}; + +#endif /* _CROSSING_H */ + diff --git a/src/geometry/FacilityGeometry.cpp b/src/geometry/FacilityGeometry.cpp index be821c5f6b2e12d45933595cf5dbd0c2be187f0c..d1053e08c7f517544a61f391cff8705ee8e02f02 100644 --- a/src/geometry/FacilityGeometry.cpp +++ b/src/geometry/FacilityGeometry.cpp @@ -30,7 +30,7 @@ */ #include "FacilityGeometry.h" -#include "Point.h" +#include "JPoint.h" #include "../SystemSettings.h" #include "LinePlotter2D.h" @@ -288,7 +288,7 @@ void FacilityGeometry::addStep(double x1, double y1, double z1, double x2, doubl linesPlotter2D->PlotDoor(m,n,doorColor/255.0); } -void FacilityGeometry::addStep(Point* p1, Point* p2){ +void FacilityGeometry::addStep(JPoint* p1, JPoint* p2){ double m[3]; double n[3]; @@ -305,7 +305,7 @@ void FacilityGeometry::addStep(Point* p1, Point* p2){ } -void FacilityGeometry::addWall(Point* p1, Point* p2, string caption){ +void FacilityGeometry::addWall(JPoint* p1, JPoint* p2, string caption){ double m[3]; double n[3]; double CHT[3]; @@ -331,7 +331,7 @@ void FacilityGeometry::addWall(Point* p1, Point* p2, string caption){ } -void FacilityGeometry::addDoor(Point* p1, Point* p2, string caption){ +void FacilityGeometry::addDoor(JPoint* p1, JPoint* p2, string caption){ double m[3]; double n[3]; @@ -465,7 +465,7 @@ void FacilityGeometry::addObjectSphere(double center[3], double radius, actor->SetMapper(mapper); actor->GetProperty()->SetColor(colorRGB); - actor->SetPosition(center[0], center[1], 0); + actor->SetPosition(center[0], center[1], center[2]); assembly2D->AddPart(actor); } } @@ -492,7 +492,7 @@ void FacilityGeometry::addObjectCylinder(double center[3], double radius, actor->SetMapper(mapper); actor->GetProperty()->SetColor(colorRGB); - actor->SetPosition(center[0], center[1], 0); + actor->SetPosition(center[0], center[1], center[2]); assembly2D->AddPart(actor); } } @@ -505,7 +505,7 @@ void FacilityGeometry::addObjectBox(double center[3], double height, { VTK_CREATE(vtkCubeSource,src); - src->SetCenter(center[0], center[1], 0); + src->SetCenter(center[0], center[1], center[2]); src->SetZLength(1); //todo: fake projection src->SetYLength(length); src->SetXLength(width); @@ -570,7 +570,7 @@ vtkActor2DCollection* FacilityGeometry::getCaptions(){ void FacilityGeometry::addNewElementText(double center[3], double orientation[3], string text, double color) { - return ; + //return ; {//caption VTK_CREATE(vtkTextActor3D,caption); diff --git a/src/geometry/FacilityGeometry.h b/src/geometry/FacilityGeometry.h index c5f9468deb0cea4d967c0520c157f64151339bc6..7b567cc970b48ce6973bf49a654f03eb7148e8e8 100644 --- a/src/geometry/FacilityGeometry.h +++ b/src/geometry/FacilityGeometry.h @@ -38,7 +38,7 @@ //forwarded classes class vtkPolyData; class vtkActor; -class Point; +class JPoint; class vtkAssembly; class vtkDataSet; class vtkLookupTable; @@ -73,18 +73,18 @@ public: ///draw a wall void addWall(double x1, double y1, double z1, double x2, double y2, double z2, double thickness=15, double height=250,double col=255); //void addWall(double center[3], double width, double orientation); - void addWall(Point* p1, Point* p2, std::string caption=""); + void addWall(JPoint* p1, JPoint* p2, std::string caption=""); ///draw a door void addDoor(double x1, double y1, double z1 ,double x2, double y2, double z2, double thickness=17, double height=250,double col=30); //void addDoor(double center[3], double width, double orientation); - void addDoor(Point* p1, Point* p2, std::string caption=""); + void addDoor(JPoint* p1, JPoint* p2, std::string caption=""); ///draw a step ///todo: implement thickness and color void addStep(double x1, double y1, double z1, double x2, double y2, double z2=0/*, double thickness=30, double height=10,double col=50*/); //void addStep(double center[3], double width, double orientation); - void addStep(Point* p1, Point* p2); + void addStep(JPoint* p1, JPoint* p2); /// draw a floor, divided in cells, void addFloor(double x1, double y1, double x2, double y2, double z=0); @@ -112,8 +112,8 @@ private: // TODO Check if this function is really necessary //vtkActor* MapToActor(vtkDataSet *ds); //for drawing floor vtkLookupTable* lookupTable; - void drawWall(Point* p1, Point* p2); - void drawDoor(Point* p1, Point* p2); + void drawWall(JPoint* p1, JPoint* p2); + void drawDoor(JPoint* p1, JPoint* p2); void addNewElement(double center[3], double orientation, double width, ELEMENT_TYPE type); void addNewElementText(double center[3], double orientation[3], std::string text, double color); diff --git a/src/geometry/Goal.cpp b/src/geometry/Goal.cpp new file mode 100644 index 0000000000000000000000000000000000000000..54aecafd0ea8f215f8d5745c798b95456d6b1892 --- /dev/null +++ b/src/geometry/Goal.cpp @@ -0,0 +1,257 @@ +/** + * @file Goal.cpp + * @author Ulrich Kemloh <kemlohulrich@gmail.com> + * Created on: Sep 12, 2013 + * Copyright (C) <2009-2013> + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#include "Goal.h" +#include "Wall.h" +#include "Point.h" + + +using namespace std; + + +Goal::Goal() { + _id=-1; + _caption="Goal"; + _isFinalGoal=0; + _walls = vector<Wall > (); + _poly = vector<Point > (); +} + +Goal::~Goal() { + +} + +void Goal::AddWall(const Wall& w) { + _walls.push_back(w); +} + +string Goal::GetCaption() const { + return _caption; +} + +void Goal::SetCaption(string caption) { + _caption = caption; +} + +int Goal::GetId() const { + return _id; +} + +void Goal::SetId(int id) { + _id = id; +} + +const vector<Point>& Goal::GetPolygon() const { + return _poly; +} + +string Goal::Write() { + string s; + Point pos; + + for (unsigned int j = 0; j < _walls.size(); j++) { + const Wall& w = _walls[j]; + s.append(w.Write()); + pos = pos + w.GetPoint1() + w.GetPoint2(); + } + pos = pos * (0.5 / _walls.size()); + + // add some fancy stuffs + if(_poly.size()>=4){ + s.append(Wall(_poly[0],_poly[2]).Write()); + s.append(Wall(_poly[1],_poly[3]).Write()); + } + //add the Goal caption + char tmp[CLENGTH]; + sprintf(tmp, "\t\t<label centerX=\"%.2f\" centerY=\"%.2f\" centerZ=\"0\" text=\"%s\" color=\"100\" />\n" + , pos.GetX() * FAKTOR, pos.GetY() * FAKTOR, _caption.c_str()); + s.append(tmp); + + return s; +} + +const vector<Wall>& Goal::GetAllWalls() const { + return _walls; +} + +int Goal::WhichQuad(const Point& vertex, const Point& hitPos) const { + return (vertex.GetX() > hitPos.GetX()) ? ((vertex.GetY() > hitPos.GetY()) ? 1 : 4) : + ((vertex.GetY() > hitPos.GetY()) ? 2 : 3); + +} + +int Goal::GetIsFinalGoal() const { + return _isFinalGoal; +} + +void Goal::SetIsFinalGoal(int isFinalGoal) { + _isFinalGoal = isFinalGoal; +} + +// x-Koordinate der Linie von einer Eccke zur nächsten +double Goal::Xintercept(const Point& point1, const Point& point2, double hitY) const { + return (point2.GetX() - (((point2.GetY() - hitY) * (point1.GetX() - point2.GetX())) / + (point1.GetY() - point2.GetY()))); +} + + +bool Goal::Contains(const Point& ped) const { + + + short edge, first, next; + short quad, next_quad, delta, total; + + ///////////////////////////////////////////////////////////// + edge = first = 0; + quad = WhichQuad(_poly[edge], ped); + total = 0; // COUNT OF ABSOLUTE SECTORS CROSSED + /* LOOP THROUGH THE VERTICES IN A SECTOR */ + do { + next = (edge + 1) % _poly.size(); + next_quad = WhichQuad(_poly[next], ped); + delta = next_quad - quad; // HOW MANY QUADS HAVE I MOVED + + // SPECIAL CASES TO HANDLE CROSSINGS OF MORE THEN ONE + //QUAD + + switch (delta) { + case 2: // IF WE CROSSED THE MIDDLE, FIGURE OUT IF IT + //WAS CLOCKWISE OR COUNTER + case -2: // US THE X POSITION AT THE HIT POINT TO + // DETERMINE WHICH WAY AROUND + if (Xintercept(_poly[edge], _poly[next], ped.GetY()) > ped.GetX()) + delta = -(delta); + break; + case 3: // MOVING 3 QUADS IS LIKE MOVING BACK 1 + delta = -1; + break; + case -3: // MOVING BACK 3 IS LIKE MOVING FORWARD 1 + delta = 1; + break; + } + /* ADD IN THE DELTA */ + total += delta; + quad = next_quad; // RESET FOR NEXT STEP + edge = next; + } while (edge != first); + + /* AFTER ALL IS DONE IF THE TOTAL IS 4 THEN WE ARE INSIDE */ + if (abs(total) == 4) + return true; + else + return false; +} + +void Goal::ConvertLineToPoly() { + + vector<Line*> copy; + vector<Point> tmpPoly; + Point point; + Line* line; + // Alle Linienelemente in copy speichern + for (unsigned int i = 0; i < _walls.size(); i++) { + copy.push_back(&_walls[i]); + } + + line = copy[0]; + tmpPoly.push_back(line->GetPoint1()); + point = line->GetPoint2(); + copy.erase(copy.begin()); + // Polygon aus allen Linen erzeugen + for (int i = 0; i < (int) copy.size(); i++) { + line = copy[i]; + if ((point - line->GetPoint1()).Norm() < J_TOLERANZ) { + tmpPoly.push_back(line->GetPoint1()); + point = line->GetPoint2(); + copy.erase(copy.begin() + i); + // von vorne suchen + i = -1; + } else if ((point - line->GetPoint2()).Norm() < J_TOLERANZ) { + tmpPoly.push_back(line->GetPoint2()); + point = line->GetPoint1(); + copy.erase(copy.begin() + i); + // von vorne suchen + i = -1; + } + } + if ((tmpPoly[0] - point).Norm() > J_TOLERANZ) { + char tmp[CLENGTH]; + sprintf(tmp, "ERROR: \tGoal::ConvertLineToPoly(): ID %d !!!\n", _id); + Log->Write(tmp); + exit(0); + } + _poly = tmpPoly; + + ComputeControid(); +} + +const Point& Goal::GetCentroid() const { + return _centroid; +} + +void Goal::ComputeControid() { + + double px=0,py=0; + double signedArea = 0.0; + double x0 = 0.0; // Current vertex X + double y0 = 0.0; // Current vertex Y + double x1 = 0.0; // Next vertex X + double y1 = 0.0; // Next vertex Y + double a = 0.0; // Partial signed area + + // For all vertices except last + unsigned int i=0; + for (i=0; i<_poly.size()-1; ++i) + { + x0 = _poly[i].GetX(); + y0 = _poly[i].GetY(); + x1 = _poly[i+1].GetX(); + y1 = _poly[i+1].GetY(); + a = x0*y1 - x1*y0; + signedArea += a; + px += (x0 + x1)*a; + py += (y0 + y1)*a; + } + + // Do last vertex + x0 = _poly[i].GetX(); + y0 = _poly[i].GetY(); + x1 = _poly[0].GetX(); + y1 = _poly[0].GetY(); + a = x0*y1 - x1*y0; + signedArea += a; + px += (x0 + x1)*a; + py += (y0 + y1)*a; + + signedArea *= 0.5; + px /= (6*signedArea); + py /= (6*signedArea); + + _centroid._x=px; + _centroid._y=py; +} diff --git a/src/geometry/Goal.h b/src/geometry/Goal.h new file mode 100644 index 0000000000000000000000000000000000000000..9efec6590455d3e9074ea56d67ce97a467e9e379 --- /dev/null +++ b/src/geometry/Goal.h @@ -0,0 +1,133 @@ +/** + * @file Goal.h + * @author Ulrich Kemloh <kemlohulrich@gmail.com> + * Created on: Sep 12, 2013 + * Copyright (C) <2009-2013> + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#ifndef GOAL_H_ +#define GOAL_H_ + +#include <string> +#include <vector> +#include "Point.h" + +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; + +}; + +#endif /* GOAL_H_ */ diff --git a/src/geometry/Hline.cpp b/src/geometry/Hline.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1600a95330b770cce308705dac397560bed5e7b9 --- /dev/null +++ b/src/geometry/Hline.cpp @@ -0,0 +1,116 @@ +/** + * Hline.cpp + * + * Created on: Aug 1, 2012 + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + + +#include "Hline.h" + +using namespace std; + +Hline::Hline() { + _room=NULL; + _subRoom=NULL; + _id=-1; +} + +Hline::~Hline() { +} + +void Hline::SetID(int ID) { + _id=ID; +} + +void Hline::SetRoom(Room* r) { + _room=r; +} + +void Hline::SetCaption(string s) { + _caption=s; +} + +void Hline::SetSubRoom(SubRoom* s) { + _subRoom=s; +} + +int Hline::GetID() const { + return _id; +} + +string Hline::GetCaption() const { + return _caption; +} + +Room* Hline::GetRoom() const { + return _room; +} + +SubRoom* Hline::GetSubRoom() const { + return _subRoom; +} + +bool Hline::IsInSubRoom(int subroomID) const { + return _subRoom->GetSubRoomID() == subroomID; +} + +bool Hline::IsInRoom(int roomID) const { + return _room->GetID() == roomID; +} + +void Hline::WriteToErrorLog() const { + string s; + char tmp[CLENGTH]; + sprintf(tmp, "\t\tHline: %d (%f, %f) -- (%f, %f)\n", GetID(), GetPoint1().GetX(), + GetPoint1().GetY(), GetPoint2().GetX(), GetPoint2().GetY()); + s.append(tmp); + sprintf(tmp, "\t\t\t\tRoom: %d <-> SubRoom: %d\n", _room->GetID(), + _subRoom->GetSubRoomID()); + s.append(tmp); + Log->Write(s); +} + +// TraVisTo Ausgabe + +string Hline::WriteElement() const { + string geometry; + char tmp[CLENGTH] = ""; + sprintf(tmp,"\t\t<door ID=\"%d\" color = \"250\" caption=\"%d_%d\">\n",GetUniqueID(),GetID(),GetUniqueID()); + geometry.append(tmp); + //geometry.append("\t\t<door color=\"250\">\n"); + sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", + (GetPoint1().GetX()) * FAKTOR, + (GetPoint1().GetY()) * FAKTOR, + _subRoom->GetElevation(GetPoint1())*FAKTOR); + geometry.append(tmp); + sprintf(tmp, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", + (GetPoint2().GetX()) * FAKTOR, + (GetPoint2().GetY()) * FAKTOR, + _subRoom->GetElevation(GetPoint2())*FAKTOR); + geometry.append(tmp); + geometry.append("\t\t</door>\n"); + return geometry; +} + + diff --git a/src/geometry/Hline.h b/src/geometry/Hline.h new file mode 100644 index 0000000000000000000000000000000000000000..120b7f0363069de177ea70438a543e4dc807710c --- /dev/null +++ b/src/geometry/Hline.h @@ -0,0 +1,114 @@ +/** + * Hline.h + * + * Created on: Aug 1, 2012 + * + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#ifndef HLINE_H_ +#define HLINE_H_ + +#include "Room.h" +#include "NavLine.h" + +class SubRoom; +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; +}; + +#endif /* HLINE_H_ */ diff --git a/src/geometry/JPoint.cpp b/src/geometry/JPoint.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d7321be1a08d600fd910b54b3c174a4b501a0afa --- /dev/null +++ b/src/geometry/JPoint.cpp @@ -0,0 +1,157 @@ +/** + * @headerfile Point.cpp + * @author Ulrich Kemloh <kemlohulrich@gmail.com> + * @version 0.1 + * Copyright (C) <2009-2010> + * + * + * @section LICENSE + * This file is part of OpenPedSim. + * + * OpenPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * OpenPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OpenPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * @brief method for plotting Plot a lot of straight lines,<br> and create a single actor to render + * + * Created on: 17.05.2009 + * + */ + +#include "JPoint.h" +#include "../Debug.h" + +#include <vtkMath.h> +#include <math.h> + +#include <cstdio> +#include <cstdlib> +#include <iostream> + +JPoint::JPoint(double xyz[3], char color[]/*="abc"*/) { + x=xyz[0]; + y=xyz[1]; + z=xyz[2]; + r=color[0]; + g=color[1]; + b=color[2]; +} + + +JPoint::JPoint(double x, double y, double z, unsigned char r/*=100*/, unsigned char g/*=100*/ , unsigned char b/*=100*/){ + this->setColorRGB(r,g, b); + this->x=x; + this->y=y; + this->z=z; + +} +JPoint::JPoint(){ + x=0; + y=0; + z=0;//creates a point centered at the origin +} + +JPoint::~JPoint() { + +} + +void JPoint::setColorRGB(unsigned char r1, unsigned char g1,unsigned char b1){ + r=r1; + g=g1; + b=b1; +} + +void JPoint::setXYZ(double*xyz){ + x=xyz[0]; + y=xyz[1]; + z=xyz[2]; +} +void JPoint::getXYZ(double*xyz){ + xyz[0]=x; + xyz[1]=y; + xyz[2]=z; +} + +/* + * return the coordinates + */ +double JPoint::getX(){return x;} +double JPoint::getY(){return y;} +double JPoint::getZ(){return z;} + +/** + * return the angle of intersection between the 2 points and the x axis + * @return the angle in degree + * FIXME: why +90?? + */ +double JPoint::angleMadeWith(JPoint& pt){ + double dx=x-pt.x; + double dy=y-pt.y; + //double dist=distanceTo(pt); + + if((dx==0) && (dy==0)){ + Debug::Error("error found in geometry"); + Debug::Error("wrong angle might be returned"); + return 0; + //return vtkMath::DegreesFromRadians(asin(dx/dist)); + } + + // return vtkMath::DegreesFromRadians(asin(dx/dist)); + return vtkMath::DegreesFromRadians(atan2(dy,dx))+90 ; +} + +double JPoint::distanceTo(JPoint& pt){ + double dx=x-pt.x; dx*=dx; + double dy=y-pt.y; dy*=dy; + double dz=z-pt.z; dz*=dz; + return sqrt(dx+dy+dz); + +} +double * JPoint::centreCoordinatesWith(JPoint &pt){ + double *res= new double[3]; + res[0]=(x+pt.getX())/2; + res[1]=(y+pt.getY())/2; + res[2]=(z+pt.getZ())/2; + return res; +} + +double JPoint::distanceBetween(JPoint& pt1, JPoint& pt2){ + return pt1.distanceTo(pt2); +} +double JPoint::angleMadeBetween(JPoint& pt1, JPoint& pt2){ + return pt1.angleMadeWith(pt2); +} +double *JPoint::centreCoordinatesBetween(JPoint& pt1, JPoint& pt2){ + return pt1.centreCoordinatesWith(pt2); +} + +/* + * return the color + */ + +unsigned char JPoint::getR(){return r;} +unsigned char JPoint::getG(){return g;} +unsigned char JPoint::getB(){return b;} + + +void JPoint::setColorHeightThicknes(double CHT[3]){ + thickness=CHT[2]; + height=CHT[1]; + color=CHT[0]; +} +void JPoint::getColorHeightThicknes(double *CHT){ + CHT[0]=color; + CHT[1]=height; + CHT[2]=thickness; +} diff --git a/src/geometry/JPoint.h b/src/geometry/JPoint.h new file mode 100644 index 0000000000000000000000000000000000000000..39446347783964dd8f2d24f8b65f29296354820e --- /dev/null +++ b/src/geometry/JPoint.h @@ -0,0 +1,77 @@ +/** +* @headerfile Point.h +* @author Ulrich Kemloh <kemlohulrich@gmail.com> +* @version 0.1 +* Copyright (C) <2009-2010> +* +* +* @section LICENSE +* This file is part of OpenPedSim. +* +* OpenPedSim is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* any later version. +* +* OpenPedSim is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with OpenPedSim. If not, see <http://www.gnu.org/licenses/>. +* +* @section DESCRIPTION +* +* @brief method for plotting Plot a lot of straight lines,<br> and create a single actor to render +* +* Created on: 17.05.2009 +* +*/ + + +#ifndef JPOINT_H_ +#define JPOINT_H_ + +class JPoint { +private: + double x,y,z; + unsigned char r,g,b; + double thickness; + double height; + double color; + +public: + JPoint(); //default constructor + JPoint(double x, double y, double z, unsigned char r='a', unsigned char g='b',unsigned char b='c'); + JPoint(double xyz[3], char col[]="abc"); + virtual ~JPoint(); + + double getX(); + double getY(); + double getZ(); + double distanceTo(JPoint& pt); + double angleMadeWith(JPoint &pt); + double* centreCoordinatesWith(JPoint &pt); + + static double distanceBetween(JPoint& pt1, JPoint& pt2); + static double angleMadeBetween(JPoint& pt1, JPoint& pt2); + static double *centreCoordinatesBetween(JPoint& pt1, JPoint& pt2); + + void setColorRGB(unsigned char r, unsigned char g, unsigned char b); + void getColorRGB(unsigned char *rgb); + + void setXYZ(double* xyz); + void getXYZ(double* xyz); + + unsigned char getR(); + unsigned char getG(); + unsigned char getB(); + + //methods for convenience in the case + //this is the end point of a door/wall for instance + void setColorHeightThicknes(double CHT[3]); + void getColorHeightThicknes(double *CHT); +}; + +#endif /* POINT_H_ */ diff --git a/src/geometry/Line.cpp b/src/geometry/Line.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1686f22f044958f65bd36ed4e2b061213649962a --- /dev/null +++ b/src/geometry/Line.cpp @@ -0,0 +1,464 @@ +/** + * File: Line.cpp + * + * Created on 30. September 2010, 09:40 + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#include "Point.h" +#include "../general/Macros.h" +#include "Line.h" + + +#include <cmath> +#include <sstream> + +int Line::_static_UID=0; + +using namespace std; + +/************************************************************ + Konstruktoren + ************************************************************/ +Line::Line() { + SetPoint1(Point()); //Default-Constructor (0.0,0.0) + SetPoint2(Point()); + _uid = _static_UID++; +} + +Line::Line(const Point& p1, const Point& p2) { + SetPoint1(p1); + SetPoint2(p2); + _uid = _static_UID++; +} + +int Line::GetUniqueID() const { + return _uid; +} + +Line::Line(const Line& orig) { + _point1 = orig.GetPoint1(); + _point2 = orig.GetPoint2(); + _centre = orig.GetCentre(); + _uid = orig.GetUniqueID(); +} + +Line::~Line() { +} + +/************************************************************* + Setter-Funktionen + ************************************************************/ +void Line::SetPoint1(const Point& p) { + _point1 = p; + _centre = (_point1+_point2)*0.5; +} + +void Line::SetPoint2(const Point& p) { + _point2 = p; + _centre = (_point1+_point2)*0.5; +} + +/************************************************************* + Getter-Funktionen + ************************************************************/ +const Point& Line::GetPoint1() const { + return _point1; +} + +const Point& Line::GetPoint2() const { + return _point2; +} + +const Point& Line::GetCentre()const { + return _centre; +} + +/************************************************************* + Ausgabe + ************************************************************/ +string Line::Write() const { + string geometry; + char wall[500] = ""; + geometry.append("\t\t<wall color=\"100\">\n"); + sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n", + (GetPoint1().GetX()) * FAKTOR, + (GetPoint1().GetY()) * FAKTOR); + geometry.append(wall); + sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n", + (GetPoint2().GetX()) * FAKTOR, + (GetPoint2().GetY()) * FAKTOR); + geometry.append(wall); + geometry.append("\t\t</wall>\n"); + return geometry; +} + + +/************************************************************* + Sonstige Funktionen + ************************************************************/ +// 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); +} + +// Normale Komponente von v auf l + +double Line::NormalComp(const Point& v) const { + // Normierte Vectoren + Point l = (GetPoint2() - GetPoint1()).Normalized(); + const Point& n = NormalVec(); + + + double 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); + } + + 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; + + tmp = p - s; + lambda = tmp.ScalarP(t) / t.ScalarP(t); + Point f = s + t*lambda; + return f; +} + +/* Punkt auf der Linie mit kürzestem Abstand zu p + * In der Regel Lotfußpunkt, Ist der Lotfußpunkt nicht im Segment + * wird der entsprechende Eckpunkt der Line genommen + * */ +Point Line::ShortestPoint(const Point& p) const { + + const Point& t = _point1 - _point2; + + 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; + + return f; +} + +/* Prüft, ob Punkt p im Liniensegment enthalten ist + * Verfahren wie bei Line::ShortestPoint(), d. h, + * 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); +//} + +/* + * Prüft, ob Punkt p im Liniensegment enthalten ist + * algorithm from: + * http://stackoverflow.com/questions/328107/how-can-you-determine-a-point-is-between-two-other-points-on-a-line-segment + * */ +bool Line::IsInLineSegment(const Point& p) const { + //const Point& _point1 = GetPoint1(); + //const Point& _point2 = GetPoint2(); + double ax = _point1.GetX(); + double ay = _point1.GetY(); + double bx = _point2.GetX(); + double by = _point2.GetY(); + double px = p._x; + double py = p._y; + + // cross product to check if point i colinear + double crossp = (py-ay)*(bx-ax)-(px-ax)*(by-ay); + if(fabs(crossp) > J_EPS) return false; + + // dotproduct and distSquared to check if point is in segment and not just in line + double dotp = (px-ax)*(bx-ax)+(py-ay)*(by-ay); + if(dotp < 0 || (_point1-_point2).NormSquare() < dotp) return false; + + return true; + +} + +/* Berechnet direkt den Abstand von p zum Segment l + * dazu wird die Funktion Line::ShortestPoint() + * benuzt + * */ +double Line::DistTo(const Point& p) const { + return (p - ShortestPoint(p)).Norm(); +} + +double Line::DistToSquare(const Point& p) const { + return (p - ShortestPoint(p)).NormSquare(); +} + +/* Zwei Linien sind gleich, wenn ihre beiden Punkte + * gleich sind + * */ +bool Line::operator==(const Line& l) const { + return ((_point1 == l.GetPoint1() && _point2 == l.GetPoint2()) || + (_point2 == l.GetPoint1() && _point1 == l.GetPoint2())); +} + +/* 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())); +} + +double Line::Length() const { + return (_point1 - _point2).Norm(); +} + +double Line::LengthSquare() const { + return (_point1 - _point2).NormSquare(); +} + +bool Line::IntersectionWith(const Line& l) const { + + //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 denominator = deltaBAx * deltaDCy - deltaBAy * deltaDCx; + double numerator = deltaACy * deltaDCx - deltaACx * deltaDCy; + + // the lines are parallel + if (denominator == 0.0) { + + // the lines are superposed + if (numerator == 0.0) { + + // the segment are superposed + if(IsInLineSegment(l.GetPoint1()) || + IsInLineSegment(l.GetPoint2()) ) return true; + else return false; + + } else { // the lines are just parallel and do not share a common point + + 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; + } + + //Point PointF = Point ((float) (_point1._x + r * deltaBAx), (float) (_point1._y + r * deltaBAy)); + //cout<< l.toString() << " intersects with " << toString() <<endl; + //cout<<" at point " << PointF.toString()<<endl; + return true; +} + +bool Line::IsHorizontal(){ + return fabs (_point1._y-_point2._y ) <= J_EPS; +} + +bool Line::IsVertical(){ + return fabs (_point1._x-_point2._x ) <= J_EPS; +} + +int Line::WichSide(const Point& pt) { + //special case for horizontal lines + if (IsVertical()) { + //left + if (pt._x < _point1._x) + return 0; + //right or colinear + if (pt._x >= _point1._x) + return 1; + } + + 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()==_point2) return true; + if(line.GetPoint2()==_point2) return true; + + return false; +} + +bool Line::HasEndPoint(const Point& point) const { + if (_point1==point) return true; + if (_point2==point) return true; + return false; +} + +bool Line::IntersectionWithCircle(const Point& centre, double radius /*cm for pedestrians*/){ + + double r=radius; + double x1=_point1.GetX(); + double y1=_point1.GetY(); + + double x2=_point2.GetX(); + double y2=_point2.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 + + // 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 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; + + 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; +} + +//TODO: Consider numerical stability and special case pt is on line +// Returns true if pt is on the left side ( from point1 toward point2) +bool Line::IsLeft(const Point& pt){ + double test=(_point2._x-_point1._x)*(pt.GetY()-_point1._y)-(_point2._y-_point1._y)*(pt.GetX()-_point1._x); + if (test>0.0) + return true; + else + return false; +} + +const Point& Line::GetLeft(const Point& pt){ + if (IsLeft(pt)){ + return _point2; + }else{ + return _point1; + } +} + +const Point& Line::GetRight(const Point& pt){ + if (!IsLeft(pt)){ + return _point2; + }else{ + return _point1; + } +} + +std::string Line::toString() const { + std::stringstream tmp; + tmp<<_point1.toString()<<"--"<<_point2.toString(); + return tmp.str(); +} diff --git a/src/geometry/Line.h b/src/geometry/Line.h new file mode 100644 index 0000000000000000000000000000000000000000..6f61c6859359ac39888a4102ce7fc0bdf5eed5b5 --- /dev/null +++ b/src/geometry/Line.h @@ -0,0 +1,222 @@ +/** + * File: Line.h + * + * Created on 30. September 2010, 09:40 + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#ifndef _LINE_H +#define _LINE_H + +#include "Point.h" +#include "../IO/OutputHandler.h" + +#include <string> + + +// external variables +extern OutputHandler* Log; + + +class Line { +private: + Point _point1; + Point _point2; + Point _centre; + + //unique identifier for all line elements + static int _static_UID; + int _uid; + +public: + + Line(); + Line(const Point& p1, const Point& p2); + Line(const Line& orig); + virtual ~Line(); + + /** + * All Line elements (also derived class) have a unique ID + * @return the unique ID of this line element. + */ + int GetUniqueID() const; + + /** + * Set/Get the first end point of the line + */ + void SetPoint1(const Point& p); + + /** + * Set/Get the second end point of the line + */ + void SetPoint2(const Point& p); + + /** + * Set/Get the first end point of the line + */ + const Point& GetPoint1(void) const; + + /** + * Set/Get the second end point of the line + */ + const Point& GetPoint2(void) const; + + /** + * Return the center of the line + */ + const Point& GetCentre(void) const; + + /** + * @return a normal vector to this line + */ + Point NormalVec() const; // Normalen_Vector zu Line + + /** + *TODO: FIXME + */ + double NormalComp(const Point& v) const; // Normale Komponente von v auf l + + /** + * Note that that result must not lie on the segment + * @return the orthogonal projection of p on the line defined by the segment points. + */ + Point LotPoint(const Point& p) const; + + /** + * @return the point on the segment with the minimum distance to p + */ + Point ShortestPoint(const Point& p) const; + + /** + * @return true if the point p lies on the line defined by the first and the second point + */ + bool IsInLine(const Point& p) const; + + /** + * @see IsInLine + * @return true if the point p is within the line segment defined the line end points + */ + bool IsInLineSegment(const Point& p) const; + + /** + * @return the distance from the line to the point p + */ + double DistTo(const Point& p) const; + + /** + * @return the distance square from the line to the point p + */ + double DistToSquare(const Point& p) const; + + /** + * @return the length (Norm) of the line + */ + double Length() const; + + /** + * @return the lenght square of the segment + */ + double LengthSquare() const; + + /** + * @return 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 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; + + +}; + +#endif /* _LINE_H */ + diff --git a/src/geometry/LinePlotter.cpp b/src/geometry/LinePlotter.cpp index 70b8c459d018dee78c1b8951b1ef9dbee1c4282e..1b9d11495669199bb7dc1f747d1eec8715fdc2d6 100644 --- a/src/geometry/LinePlotter.cpp +++ b/src/geometry/LinePlotter.cpp @@ -42,7 +42,7 @@ #include <vtkSmartPointer.h> -#include "Point.h" +#include "JPoint.h" #include "./src/SystemSettings.h" #include "LinePlotter.h" @@ -110,7 +110,7 @@ void LinePlotter::SetNumberOfPoints(int nPoints) { } -void LinePlotter::PlotLine(Point* pt1, Point* pt2) { +void LinePlotter::PlotLine(JPoint* pt1, JPoint* pt2) { double m[3], n[3]; unsigned char col[3]; @@ -131,7 +131,7 @@ void LinePlotter::PlotLine(Point* pt1, Point* pt2) { } -void LinePlotter::addVertex(Point *pt1) { +void LinePlotter::addVertex(JPoint *pt1) { double m[3]; unsigned char col[3]; @@ -163,7 +163,7 @@ void LinePlotter::addVertex(Point *pt1) { void LinePlotter::addVertex(double vertex[3],double col[3]) { - Point *pts = new Point(); + JPoint *pts = new JPoint(); pts->setColorRGB(col[0],col[1],col[2]); pts->setXYZ(vertex); addVertex(pts); diff --git a/src/geometry/LinePlotter.h b/src/geometry/LinePlotter.h index 299209269c48268ee95da3c20cc306f5e5613761..b10885cec327fe6a9c75a93579c18fe912d62c7e 100644 --- a/src/geometry/LinePlotter.h +++ b/src/geometry/LinePlotter.h @@ -40,7 +40,7 @@ class vtkFloatArray ; class vtkActor ; class vtkPolyData; class vtkDataArray; -class Point; +class JPoint; class LinePlotter @@ -53,12 +53,12 @@ public: //void SetScalarRange(double minval=0.0, double maxval=1.0); //void SetLookupTable(vtkLookupTable* table = 0); - void PlotLine(Point* pt1, Point* pt2); + void PlotLine(JPoint* pt1, JPoint* pt2); void PlotLine(double m[3], double n[3], unsigned char scalar[3]); void PlotLine(double x, double y, double z, double x2, double y2, double z2, unsigned char scalar[3]); void addVertex(double vertex[3],double scalar[3]); - void addVertex(Point* pt1); + void addVertex(JPoint* pt1); void SetNumberOfPoints(int nPoints); void clear(); static void setLineWidth(int width=1); diff --git a/src/geometry/NavLine.cpp b/src/geometry/NavLine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ade179a33d520ace2144c3be73eb4e6cec455ee4 --- /dev/null +++ b/src/geometry/NavLine.cpp @@ -0,0 +1,44 @@ +/** + * NavLine.cpp + * + * Created on: Aug 30, 2012 + * + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#include "NavLine.h" + + + +NavLine::NavLine() { + +} + +NavLine::NavLine(Line l):Line(l) { + +} + +NavLine::~NavLine() { +} + + diff --git a/src/geometry/NavLine.h b/src/geometry/NavLine.h new file mode 100644 index 0000000000000000000000000000000000000000..442ffa8b919d367945d78c01e6f55b8a292c6fda --- /dev/null +++ b/src/geometry/NavLine.h @@ -0,0 +1,42 @@ +/** + * NavLine.h + * + * Created on: Aug 30, 2012 + * + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#ifndef NAVLINE_H_ +#define NAVLINE_H_ +#include "Line.h" + +class NavLine: public Line { + +public: + NavLine(); + NavLine(Line l); + virtual ~NavLine(); + +}; + +#endif /* NAVLINE_H_ */ diff --git a/src/geometry/Obstacle.cpp b/src/geometry/Obstacle.cpp new file mode 100644 index 0000000000000000000000000000000000000000..89eecf0c0861ce881c9f177843d9599edc26d12f --- /dev/null +++ b/src/geometry/Obstacle.cpp @@ -0,0 +1,293 @@ +/** + * Obstacle.cpp + * + * Created on: Jul 31, 2012 + * + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#include "Obstacle.h" + +#include <cmath> +#include <cstdio> +#include <cstdlib> +#include <iterator> +#include <string> +#include <vector> + +#include "../IO/OutputHandler.h" +#include "Line.h" +#include "Point.h" +#include "Wall.h" + + +using namespace std; + + +Obstacle::Obstacle() { + _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); +} + +string Obstacle::GetCaption() const { + return _caption; +} + +void Obstacle::SetCaption(string caption) { + _caption = caption; +} + +double Obstacle::GetClosed() const { + return _isClosed; +} + +void Obstacle::SetClosed(double closed) { + _isClosed = closed; +} + +double Obstacle::GetHeight() const { + return _height; +} + +void Obstacle::SetHeight(double height) { + _height = height; +} + +int Obstacle::GetId() const { + return _id; +} + +void Obstacle::SetId(int id) { + _id = id; +} + +const vector<Point>& Obstacle::GetPolygon() const { + return _poly; +} + +string Obstacle::Write() { + string s; + //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()); + + Point pos = GetCentroid(); + + //add the obstacle caption + char tmp[CLENGTH]; + //sprintf(tmp, "\t\t<label centerX=\"%.2f\" centerY=\"%.2f\" centerZ=\"0\" text=\"%s\" color=\"100\" />\n" + // , pos.GetX() * FAKTOR, pos.GetY() * FAKTOR, _caption.c_str()); + + sprintf(tmp, "\t\t<label centerX=\"%.2f\" centerY=\"%.2f\" centerZ=\"0\" text=\"%d\" color=\"100\" />\n" + , pos.GetX() * FAKTOR, pos.GetY() * FAKTOR, _id); + s.append(tmp); + + return s; +} + +const vector<Wall>& Obstacle::GetAllWalls() const { + return _walls; +} + +int Obstacle::WhichQuad(const Point& vertex, const Point& hitPos) const { + return (vertex.GetX() > hitPos.GetX()) ? ((vertex.GetY() > hitPos.GetY()) ? 1 : 4) : + ((vertex.GetY() > hitPos.GetY()) ? 2 : 3); + +} + +// x-Koordinate der Linie von einer Eccke zur nächsten +double Obstacle::Xintercept(const Point& point1, const Point& point2, double hitY) const { + return (point2.GetX() - (((point2.GetY() - hitY) * (point1.GetX() - point2.GetX())) / + (point1.GetY() - point2.GetY()))); +} + + +bool Obstacle::Contains(const Point& ped) const { + + // 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; +} + +const Point Obstacle::GetCentroid() const{ + + double px=0,py=0; + double signedArea = 0.0; + double x0 = 0.0; // Current vertex X + double y0 = 0.0; // Current vertex Y + double x1 = 0.0; // Next vertex X + double y1 = 0.0; // Next vertex Y + double a = 0.0; // Partial signed area + + // For all vertices except last + unsigned int i=0; + for (i=0; i<_poly.size()-1; ++i) + { + x0 = _poly[i].GetX(); + y0 = _poly[i].GetY(); + x1 = _poly[i+1].GetX(); + y1 = _poly[i+1].GetY(); + a = x0*y1 - x1*y0; + signedArea += a; + px += (x0 + x1)*a; + py += (y0 + y1)*a; + } + + // Do last vertex + x0 = _poly[i].GetX(); + y0 = _poly[i].GetY(); + x1 = _poly[0].GetX(); + y1 = _poly[0].GetY(); + a = x0*y1 - x1*y0; + signedArea += a; + px += (x0 + x1)*a; + py += (y0 + y1)*a; + + signedArea *= 0.5; + px /= (6*signedArea); + py /= (6*signedArea); + + return Point (px,py); +} + + +bool Obstacle::IntersectWithLine(const Line& line) const { + + for (unsigned int i=0;i<_walls.size();i++){ + + if(_walls[i].IntersectionWith(line)) return true; + } + + return false; +} diff --git a/src/geometry/Obstacle.h b/src/geometry/Obstacle.h new file mode 100644 index 0000000000000000000000000000000000000000..79d3ed2c74946927865b0de849ef4804168ab4e5 --- /dev/null +++ b/src/geometry/Obstacle.h @@ -0,0 +1,146 @@ +/** + * Obstacle.h + * + * Created on: Jul 31, 2012 + * + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#ifndef OBSTACLE_H_ +#define OBSTACLE_H_ + +#include <string> +#include <vector> + +#include "Point.h" +#include "Wall.h" + + +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; + +}; + +#endif /* OBSTACLE_H_ */ diff --git a/src/geometry/Point.cpp b/src/geometry/Point.cpp index 2a884aa038bdbb127ca17282a3072cf610d8af31..3f7256225da035635d0d774325461fce55fa8f0f 100644 --- a/src/geometry/Point.cpp +++ b/src/geometry/Point.cpp @@ -1,157 +1,243 @@ -/** - * @headerfile Point.cpp - * @author Ulrich Kemloh <kemlohulrich@gmail.com> - * @version 0.1 - * Copyright (C) <2009-2010> - * - * - * @section LICENSE - * This file is part of OpenPedSim. - * - * OpenPedSim is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * OpenPedSim is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with OpenPedSim. If not, see <http://www.gnu.org/licenses/>. - * - * @section DESCRIPTION - * - * @brief method for plotting Plot a lot of straight lines,<br> and create a single actor to render - * - * Created on: 17.05.2009 - * - */ - -#include "Point.h" -#include "../Debug.h" - -#include <vtkMath.h> -#include <math.h> - -#include <cstdio> -#include <cstdlib> -#include <iostream> - -Point::Point(double xyz[3], char color[]/*="abc"*/) { - x=xyz[0]; - y=xyz[1]; - z=xyz[2]; - r=color[0]; - g=color[1]; - b=color[2]; -} - - -Point::Point(double x, double y, double z, unsigned char r/*=100*/, unsigned char g/*=100*/ , unsigned char b/*=100*/){ - this->setColorRGB(r,g, b); - this->x=x; - this->y=y; - this->z=z; - -} -Point::Point(){ - x=0; - y=0; - z=0;//creates a point centered at the origin -} - -Point::~Point() { - -} - -void Point::setColorRGB(unsigned char r1, unsigned char g1,unsigned char b1){ - r=r1; - g=g1; - b=b1; -} - -void Point::setXYZ(double*xyz){ - x=xyz[0]; - y=xyz[1]; - z=xyz[2]; -} -void Point::getXYZ(double*xyz){ - xyz[0]=x; - xyz[1]=y; - xyz[2]=z; -} - -/* - * return the coordinates - */ -double Point::getX(){return x;} -double Point::getY(){return y;} -double Point::getZ(){return z;} - -/** - * return the angle of intersection between the 2 points and the x axis - * @return the angle in degree - * FIXME: why +90?? - */ -double Point::angleMadeWith(Point& pt){ - double dx=x-pt.x; - double dy=y-pt.y; - //double dist=distanceTo(pt); - - if((dx==0) && (dy==0)){ - Debug::Error("error found in geometry"); - Debug::Error("wrong angle might be returned"); - return 0; - //return vtkMath::DegreesFromRadians(asin(dx/dist)); - } - - // return vtkMath::DegreesFromRadians(asin(dx/dist)); - return vtkMath::DegreesFromRadians(atan2(dy,dx))+90 ; -} - -double Point::distanceTo(Point& pt){ - double dx=x-pt.x; dx*=dx; - double dy=y-pt.y; dy*=dy; - double dz=z-pt.z; dz*=dz; - return sqrt(dx+dy+dz); - -} -double * Point::centreCoordinatesWith(Point &pt){ - double *res= new double[3]; - res[0]=(x+pt.getX())/2; - res[1]=(y+pt.getY())/2; - res[2]=(z+pt.getZ())/2; - return res; -} - -double Point::distanceBetween(Point& pt1, Point& pt2){ - return pt1.distanceTo(pt2); -} -double Point::angleMadeBetween(Point& pt1, Point& pt2){ - return pt1.angleMadeWith(pt2); -} -double *Point::centreCoordinatesBetween(Point& pt1, Point& pt2){ - return pt1.centreCoordinatesWith(pt2); -} - -/* - * return the color - */ - -unsigned char Point::getR(){return r;} -unsigned char Point::getG(){return g;} -unsigned char Point::getB(){return b;} - - -void Point::setColorHeightThicknes(double CHT[3]){ - thickness=CHT[2]; - height=CHT[1]; - color=CHT[0]; -} -void Point::getColorHeightThicknes(double *CHT){ - CHT[0]=color; - CHT[1]=height; - CHT[2]=thickness; -} +/** + * File: Point.cpp + * + * Created on 30. September 2010, 09:21 + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#include "Point.h" +#include "../general/Macros.h" + +#include <iostream> +#include <cmath> +#include <sstream> + + + + + +/************************************************************ + Konstruktoren + ************************************************************/ +Point::Point() { + _x = 0.0; + _y = 0.0; +} + +Point::Point(double x, double y) { + _x = x; + _y = y; +} + +Point::Point(const Point& orig) { + _x = orig.GetX(); + _y = orig.GetY(); +} + +std::string Point::toString() const { + std::stringstream tmp; + tmp<<"( "<<_x<<" : " <<_y<<" )"; + return tmp.str(); +}; + +void Point::SetX(double x) { + _x = x; +} + +void Point::SetY(double y) { + _y = y; +} + +double Point::GetX() const { + return _x; +} + +double Point::GetY() const { + return _y; +} + +double Point::Norm() const { + return sqrt(_x * _x + _y * _y); +} + +double Point::NormSquare() const { + return (_x * _x + _y * _y); +} + +Point Point::Normalized() const { + double norm=Norm(); + if (norm > J_EPS*J_EPS) + return ( Point(_x, _y) / norm ); + else return Point(0.0, 0.0); +} + +// scalar product +double Point::ScalarP(const Point& v) const { + //return _x * v.GetX() + _y * v.GetY(); + return _x * v._x + _y * v._y; +} + +/// determinant of the square matrix formed by the vectors [ this, v] +double Point::Det(const Point& v) const { + return _x * v._y - _y * v._x; +} + +/* Transformiert die "normalen" Koordinaten in Koordinaten der Ellipse + * dazu verschieben des Koordinaten Ursprungs in Center und anschliessend drehen um phi + * alle Punkte müssen in "normalen" Koordinaten gegeben sein + * center: Center der Ellipse in deren System transformiert werden soll + * phi: Winkel der Ellipse in deren System transformiert werden soll + * */ + + +/*coordinate transformation of the point P(x,y) expressed in coord system S1 to a new coord. sys S2 + + A + * + | S_2 + \ | / + | \ | / + | \ | /^phi + | yc___\ /_)_________ S_3 + | O1 + | | + | | + | xc + | + |___________________________ +O +S_1 + + +//////////////////////////////////// +S_1 is cartesian coordinate system!! +//////////////////////////////////// + + input: + - (x,y) : coordinates of the point A in S_1 + - (xc,yc) : coordinate of the center in the S_1 (Center of Ellipse) + - phi : angle between the S_1 and S_2 + + output: + + (xnew,ynew) : new coordinate of the point A in the coord. sys S2 + +OA = OO1 + O1A + + [x ; y] = [xc ; yc] + [x_3 ; y_3] : (1) ( with [x_i ; y_i] coordinats of P in S_i and i in {1,2,3} ) + +[x_2 ; y_2] = M(phi) * [x_3 ; y_3] : (2) + + +(1) in (2)---> + +--> [x_2 ; y_2] = M(phi) * ([x ; y] - [xc ; yc]) + + + +after rotation: +OC = OO1 +O1C +OC = -O1O +O1C + +xnew = -xc + x + +*/ +Point Point::CoordTransToEllipse(const Point& center, double cphi, double sphi) const { + Point p = Point(_x, _y); + return (p - center).Rotate(cphi, -sphi); +} + +/* +This is the reverse funktion of CoordTransToEllipse(), +where the coord. of a point are transformated to cart. coord. + + input: + - (x,y) : coordinates of the point P in S_2 + - (xc,yc) : coordinate of the center in the S_1 (Center of Ellipse) + - phi : angle between the S_1 and S_2 + + output: + + (xnew,ynew) : new coordinate of the point P in the coord. sys S_1 + +[x_2 ; y_2] = M(phi) * ([x ; y] - [xc ; yc]) (see comments in CoordTransToEllipse() ) + + +----> [x ; y] = M(-phi) * [x_2 ; y_2] + [xc ; yc] + +*/ + +Point Point::CoordTransToCart(const Point& center, double cphi, double sphi) const { + Point p = Point(_x, _y); + return (p.Rotate(cphi, sphi) + center); +} + +/*rotate a two-dimensional vector by an angle of theta + +Rotation-matrix=[cos(theta) -sin(theta)] + [ sin(theta) cos(theta)] + +*/ +Point Point::Rotate(double ctheta, double stheta) const { + return Point(_x * ctheta - _y*stheta, _x * stheta + _y * ctheta); +} + +// sum +const Point Point::operator+(const Point& p) const { + //return Point(_x + p.GetX(), _y + p.GetY()); + return Point(_x + p._x, _y + p._y); +} + +// sub +const Point Point::operator-(const Point& p) const { + // return Point(_x - p.GetX(), _y - p.GetY()); + return Point(_x - p._x, _y - p._y); +} + +// equal +bool Point::operator==(const Point& p) const { +// return (fabs(_x - p.GetX()) < J_EPS && fabs(_y - p.GetY()) < J_EPS); + return (fabs(_x - p._x) < J_EPS && fabs(_y - p._y) < J_EPS); +} + +// not equal +bool Point::operator!=(const Point& p) const { + //return (fabs(_x - p.GetX()) > J_EPS || fabs(_y - p.GetY()) > J_EPS); + return (fabs(_x - p._x) > J_EPS || fabs(_y - p._y) > J_EPS); +} + + +// multiplication with scalar +const Point operator*(const Point& p, double f) { + //return Point(p.GetX() * f, p.GetY() * f); + return Point(p._x * f, p._y * f); +} + +// divition with scalar +const Point operator/(const Point& p, double f) { + if (f>J_EPS*J_EPS) + return Point(p._x / f, p._y / f); + else + { + std::cout << "Warning: Point::/operator. dividand "<<f<< " is to small. Set it to 1 instead"<<std::endl; + return Point(p._x, p._y); + } + //return Point(p.GetX() / f, p.GetY() / f); +} diff --git a/src/geometry/Point.h b/src/geometry/Point.h index f6f82e74608a720214d3990206aaf3b5dc0167a3..46dcca7b19c4f4afc22d433b237c8f6461af361e 100644 --- a/src/geometry/Point.h +++ b/src/geometry/Point.h @@ -1,77 +1,103 @@ -/** -* @headerfile Point.h -* @author Ulrich Kemloh <kemlohulrich@gmail.com> -* @version 0.1 -* Copyright (C) <2009-2010> -* -* -* @section LICENSE -* This file is part of OpenPedSim. -* -* OpenPedSim is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* any later version. -* -* OpenPedSim is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with OpenPedSim. If not, see <http://www.gnu.org/licenses/>. -* -* @section DESCRIPTION -* -* @brief method for plotting Plot a lot of straight lines,<br> and create a single actor to render -* -* Created on: 17.05.2009 -* -*/ - - -#ifndef POINT_H_ -#define POINT_H_ - -class Point { -private: - double x,y,z; - unsigned char r,g,b; - double thickness; - double height; - double color; - -public: - Point(); //default constructor - Point(double x, double y, double z, unsigned char r='a', unsigned char g='b',unsigned char b='c'); - Point(double xyz[3], char col[]="abc"); - virtual ~Point(); - - double getX(); - double getY(); - double getZ(); - double distanceTo(Point& pt); - double angleMadeWith(Point &pt); - double* centreCoordinatesWith(Point &pt); - - static double distanceBetween(Point& pt1, Point& pt2); - static double angleMadeBetween(Point& pt1, Point& pt2); - static double *centreCoordinatesBetween(Point& pt1, Point& pt2); - - void setColorRGB(unsigned char r, unsigned char g, unsigned char b); - void getColorRGB(unsigned char *rgb); - - void setXYZ(double* xyz); - void getXYZ(double* xyz); - - unsigned char getR(); - unsigned char getG(); - unsigned char getB(); - - //methods for convenience in the case - //this is the end point of a door/wall for instance - void setColorHeightThicknes(double CHT[3]); - void getColorHeightThicknes(double *CHT); -}; - -#endif /* POINT_H_ */ +/** + * File: Point.h + * + * Created on 30. September 2010, 09:21 + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#ifndef _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; +}; + +/// multiplication +const Point operator*(const Point& p, const double f); +/// division +const Point operator/(const Point& p, const double f); + +#endif /* _POINT_H */ + diff --git a/src/geometry/PointPlotter.cpp b/src/geometry/PointPlotter.cpp index c0f3eab066b73cae4bc642596f3a76ed0f153c03..f8efa832cc0905cc463f6e80d7f3b4112e745082 100644 --- a/src/geometry/PointPlotter.cpp +++ b/src/geometry/PointPlotter.cpp @@ -16,7 +16,7 @@ #include <vtkPointData.h> #include <vtkSmartPointer.h> -#include "Point.h" +#include "JPoint.h" #include "PointPlotter.h" #include "./src/SystemSettings.h" @@ -91,7 +91,7 @@ PointPlotter::~PointPlotter() * add a point to the plot */ -void PointPlotter::PlotPoint(Point * point){ +void PointPlotter::PlotPoint(JPoint * point){ double x=point->getX(); double y=point->getY(); double z=point->getZ(); diff --git a/src/geometry/PointPlotter.h b/src/geometry/PointPlotter.h index a017f6d9c454f1d54ce2732beb9b4ccd08258bee..9d5e48120d21e8721c88351cbcdca1a533ca41c1 100644 --- a/src/geometry/PointPlotter.h +++ b/src/geometry/PointPlotter.h @@ -41,7 +41,7 @@ class vtkUnsignedCharArray ; class vtkPolyData ; class vtkActor ; class vtkDataArray ; -class Point; +class JPoint; class PointPlotter { @@ -54,7 +54,7 @@ public: void PlotPoint(double x, double y, double z, unsigned char r='a', unsigned char g='b', unsigned char b='c'); - void PlotPoint(Point* pt); + void PlotPoint(JPoint* pt); void SetPointRadius(double radius = 1.0) { pt_radius = radius ; } void SetPointResolution(int res = 15) { pt_res = res ;} diff --git a/src/geometry/Room.cpp b/src/geometry/Room.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c256a071ba1f3f2be01d6153932258989f93014 --- /dev/null +++ b/src/geometry/Room.cpp @@ -0,0 +1,192 @@ +/** + * File: Room.cpp + * + * Created on 30. September 2010, 11:58 + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + + +#include "Room.h" +#include <sstream> + +using namespace std; + +/************************************************************ + Konstruktoren + ************************************************************/ + +Room::Room() { + _id = -1; + _state=ROOM_CLEAN; //smoke-free + _caption = "no room caption"; + _zPos = -1.0; + _subRooms = vector<SubRoom* > (); + _outputFile=NULL; +} + +Room::Room(const Room& orig) { + _id = orig.GetID(); + _caption = orig.GetCaption(); + _zPos = orig.GetZPos(); + _subRooms = orig.GetAllSubRooms(); + _state=orig.GetState(); + _outputFile=orig.GetOutputHandler(); +} + +Room::~Room() { + for (unsigned int i = 0; i < _subRooms.size(); i++) + delete _subRooms[i]; +} + +/************************************************************* + Setter-Funktionen + ************************************************************/ +void Room::SetID(int ID) { + _id = ID; +} + +void Room::SetCaption(string s) { + _caption = s; +} + +void Room::SetZPos(double z) { + _zPos = z; +} + +void Room::SetSubRoom(SubRoom* subroom, int index) { + if ((index >= 0) && (index < GetNumberOfSubRooms())) { + _subRooms[index] = subroom; + } else { + Log->Write("ERROR: Wrong Index in Room::SetSubRoom()"); + exit(0); + } +} + +void Room::SetState(RoomState state) { + _state=state; +} + + +/************************************************************* + Getter-Functions + ************************************************************/ +int Room::GetID() const { + return _id; +} + +string Room::GetCaption() const { + return _caption; +} + +double Room::GetZPos() const { + //if(pCaption=="070") return pZPos+1.0; + return _zPos; +} + +int Room::GetNumberOfSubRooms() const { + return _subRooms.size(); +} + +const vector<SubRoom*>& Room::GetAllSubRooms() const { + return _subRooms; +} + +SubRoom* Room::GetSubRoom(int index) const { + if ((index >= 0) && (index < (int) _subRooms.size())) + return _subRooms[index]; + else { + char tmp[CLENGTH]; + sprintf(tmp,"ERROR: Room::GetSubRoom() Wrong subroom index [%d] for room index [%d] ",index,_id); + Log->Write(tmp); + exit(0); + } +} + + +#ifdef _SIMULATOR + +int Room::GetNumberOfPedestrians() const { + int sum = 0; + for (int i = 0; i < GetNumberOfSubRooms(); i++) { + sum += GetSubRoom(i)->GetNumberOfPedestrians(); + } + return sum; +} + +#endif // _SIMULATOR + +RoomState Room::GetState() const { + return _state; +} + + + +/************************************************************* + Sonstige Funktionen + ************************************************************/ +void Room::AddSubRoom(SubRoom* r) { + _subRooms.push_back(r); +} + +void Room::DeleteSubRoom(int index) { + if ((index >= 0) && (index < (int) _subRooms.size())) + _subRooms.erase(_subRooms.begin() + index); + else { + Log->Write("ERROR: Wrong Index in Room::DeleteSubRoom()"); + exit(0); + } +} + +/************************************************************* + Ein-Ausgabe + ************************************************************/ + + +void Room::WriteToErrorLog() const { + char tmp[CLENGTH]; + string s; + sprintf(tmp, "\tRaum: %d [%s]:\n", _id, _caption.c_str()); + s.append(tmp); + Log->Write(s); + // SubRooms + for (int i = 0; i < GetNumberOfSubRooms(); i++) { + SubRoom* s = GetSubRoom(i); + s->WriteToErrorLog(); + } + +} + +const vector<int>& Room::GetAllTransitionsIDs() const { + return _transitionsIDs; +} + +void Room::AddTransitionID(int ID){ + _transitionsIDs.push_back(ID); +} + +void Room::SetOutputHandler(OutputHandler* oh){ + _outputFile=oh; +} + +OutputHandler* Room::GetOutputHandler() const { + return _outputFile; +} diff --git a/src/geometry/Room.h b/src/geometry/Room.h new file mode 100644 index 0000000000000000000000000000000000000000..7917089bc9899b8a92036f9c140313c95fd31be5 --- /dev/null +++ b/src/geometry/Room.h @@ -0,0 +1,163 @@ +/** + * \file File: Room.h + * + * Created on 30. September 2010, 11:58 + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + */ + +#ifndef _ROOM_H +#define _ROOM_H + +#include <string> +#include <algorithm> + +#include "../geometry/SubRoom.h" +//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; + +}; + +#endif /* _ROOM_H */ + diff --git a/src/geometry/SubRoom.cpp b/src/geometry/SubRoom.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e0868cdc73453984f1fa41b048cb73dac0d41442 --- /dev/null +++ b/src/geometry/SubRoom.cpp @@ -0,0 +1,1019 @@ +/** + * File: SubRoom.cpp + * + * Created on 8. October 2010, 10:56 + * + * @section LICENSE + * + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#include "Obstacle.h" +#include "SubRoom.h" +#include "Transition.h" +#include "Hline.h" +#include "Wall.h" + +#ifdef _SIMULATOR +#include "../pedestrian/Pedestrian.h" +#endif //_SIMULATOR + +#include <cmath> + +using namespace std; + +/************************************************************ + SubRoom + ************************************************************/ + +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++; + +#ifdef _SIMULATOR + _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(); + +#ifdef _SIMULATOR + _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(); + +#ifdef _SIMULATOR + for (unsigned int i = 0; i < _peds.size(); i++) { + delete _peds[i]; + } +#endif //_SIMULATOR + +} + +// Setter -Funktionen + +void SubRoom::SetSubRoomID(int ID) { + _id = ID; +} +void SubRoom::SetClosed(double closed) { + _closed = closed; +} + +void SubRoom::SetRoomID(int ID) { + _roomID = ID; +} + +int SubRoom::GetSubRoomID() const { + return _id; +} + +double SubRoom::GetClosed() const { + return _closed; +} + +// unique identifier for this subroom +int SubRoom::GetUID() const { + return _uid; + //return pRoomID * 1000 + pID; +} + +double SubRoom::GetArea() const { + return _area; +} + +int SubRoom::GetRoomID() const { + return _roomID; +} + +int SubRoom::GetNumberOfWalls() const { + return _walls.size(); +} + +const vector<Wall>& SubRoom::GetAllWalls() const { + return _walls; +} + +const Wall& SubRoom::GetWall(int index) const { + if ((index >= 0) && (index < GetNumberOfWalls())) + return _walls[index]; + else { + Log->Write("ERROR: Wrong 'index' in SubRoom::GetWall()"); + exit(0); + } +} + +const vector<Point>& SubRoom::GetPolygon() const { + return _poly; +} + +const vector<Obstacle*>& SubRoom::GetAllObstacles() const { + return _obstacles; +} + +int SubRoom::GetNumberOfGoalIDs() const { + return _goalIDs.size(); +} + +const vector<int>& SubRoom::GetAllGoalIDs() const { + return _goalIDs; +} + + +// Sonstiges + +void SubRoom::AddWall(const Wall& w) { + _walls.push_back(w); +} + + +void SubRoom::AddObstacle(Obstacle* obs){ + _obstacles.push_back(obs); + CheckObstacles(); +} + + +void SubRoom::AddGoalID(int ID) { + _goalIDs.push_back(ID); +} + +void SubRoom::AddCrossing(Crossing* line){ + _crossings.push_back(line); + _goalIDs.push_back(line->GetUniqueID()); +} + +void SubRoom::AddTransition(Transition* line){ + _transitions.push_back(line); + _goalIDs.push_back(line->GetUniqueID()); +} + +void SubRoom::AddHline(Hline* line){ + _hlines.push_back(line); + _goalIDs.push_back(line->GetUniqueID()); +} + +const vector<Crossing*>& SubRoom::GetAllCrossings() const{ + return _crossings; +} + +const vector<Transition*>& SubRoom::GetAllTransitions() const{ + return _transitions; +} + +const vector<Hline*>& SubRoom::GetAllHlines() const{ + return _hlines; +} + +const Crossing* SubRoom::GetCrossing(int i) const { + return _crossings[i]; +} + +const Transition* SubRoom::GetTransition(int i) const { + return _transitions[i]; +} + +const Hline* SubRoom::GetHline(int i) const { + return _hlines[i]; +} + +void SubRoom::RemoveGoalID(int ID){ + for (unsigned int i=0;i<_goalIDs.size();i++){ + if(_goalIDs[i]==ID){ + Log->Write("Removing goal"); + _goalIDs.erase(_goalIDs.begin()+i); + return; + } + } + Log->Write("There is no goal with that id to remove"); +} + + +void SubRoom::CalculateArea() { + double sum = 0; + int n = (int) _poly.size(); + for (int i = 0; i < n; i++) { + sum += (_poly[i].GetY() + _poly[(i + 1) % n].GetY())*(_poly[i].GetX() - _poly[(i + 1) % n].GetX()); + } + _area=(0.5 * fabs(sum)); +} + +Point SubRoom::GetCentroid() const { + + double px=0,py=0; + double signedArea = 0.0; + double x0 = 0.0; // Current vertex X + double y0 = 0.0; // Current vertex Y + double x1 = 0.0; // Next vertex X + double y1 = 0.0; // Next vertex Y + double a = 0.0; // Partial signed area + + // For all vertices except last + unsigned int i=0; + for (i=0; i<_poly.size()-1; ++i) + { + x0 = _poly[i].GetX(); + y0 = _poly[i].GetY(); + x1 = _poly[i+1].GetX(); + y1 = _poly[i+1].GetY(); + a = x0*y1 - x1*y0; + signedArea += a; + px += (x0 + x1)*a; + py += (y0 + y1)*a; + } + + // Do last vertex + x0 = _poly[i].GetX(); + y0 = _poly[i].GetY(); + x1 = _poly[0].GetX(); + y1 = _poly[0].GetY(); + a = x0*y1 - x1*y0; + signedArea += a; + px += (x0 + x1)*a; + py += (y0 + y1)*a; + + signedArea *= 0.5; + px /= (6.0*signedArea); + py /= (6.0*signedArea); + + 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(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]; +} + + + + +// this is the case if they share a transition or crossing +bool SubRoom::IsDirectlyConnectedWith(const SubRoom* sub) const { + + //check the crossings + const vector<Crossing*>& crossings = sub->GetAllCrossings(); + for (unsigned int i = 0; i < crossings.size(); i++) { + for (unsigned int j = 0; j < _crossings.size(); j++) { + int uid1 = crossings[i]->GetUniqueID(); + int uid2 = _crossings[j]->GetUniqueID(); + // ignore my transition + if (uid1 == uid2) + return true; + } + } + + // and finally the transitions + const vector<Transition*>& transitions = sub->GetAllTransitions(); + for (unsigned int i = 0; i < transitions.size(); i++) { + for (unsigned int j = 0; j < _transitions.size(); j++) { + int uid1 = transitions[i]->GetUniqueID(); + int uid2 = _transitions[j]->GetUniqueID(); + // ignore my transition + if (uid1 == uid2) + return true; + } + } + + return false; +} + +void SubRoom::SetPlanEquation(double A, double B, double C) { + _planeEquation[0]=A; + _planeEquation[1]=B; + _planeEquation[2]=C; + //compute and cache the cosine of angle with the plane z=h + _cosAngleWithHorizontalPlane= (1.0/sqrt(A*A+B*B+1)); +} + +const double* SubRoom::GetPlanEquation() const { + return _planeEquation; +} + +double SubRoom::GetElevation(const Point& p) const { + return _planeEquation[0] * p._x + _planeEquation[1] * p._y + _planeEquation[2]; +} + +double SubRoom::GetCosAngleWithHorizontal() const { + return _cosAngleWithHorizontalPlane; + +} + +void SubRoom::CheckObstacles(){ + for(unsigned int i = 0; i<_walls.size();i++){ + for(unsigned int j = 0; j<_obstacles.size();j++){ + if(_obstacles[j]->IntersectWithLine(_walls[i])){ + Log->Write("INFO: \tthe obstacle id [%d] is intersection with subroom [%d]",_obstacles[j]->GetId(),_id); + Log->Write("INFO: \tthe triangulation will not work."); + exit(EXIT_FAILURE); + } + } + } +} + +void SubRoom::SanityCheck(){ + if(_obstacles.size()==0){ + if((IsConvex()==false) && (_hlines.size()==0)){ + Log->Write("WARNING:\t Room [%d] Subroom [%d] is not convex!",_roomID,_id); + Log->Write("\t\t you might consider adding extra hlines in your routing.xml file"); + } else { + // everything is fine + } + } else { + if(_hlines.size()==0){ + Log->Write("WARNING:\t you have obstacles in room [%d] Subroom [%d]!",_roomID,_id); + Log->Write("\t\t you might consider adding extra hlines in your routing.xml file"); + }else { + // everything is fine + } + } + +} + +///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; +} + +///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); + } + + 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; + + return ( det<=0.0 ); +} + + +/************************************************************ + NormalSubRoom + ************************************************************/ +NormalSubRoom::NormalSubRoom() : SubRoom() { + +} + +NormalSubRoom::NormalSubRoom(const NormalSubRoom& orig) : SubRoom(orig) { + +} + +NormalSubRoom::~NormalSubRoom() { +} + +string NormalSubRoom::WriteSubRoom() const { + string s; + for (int j = 0; j < GetNumberOfWalls(); j++) { + + const Wall& w = GetWall(j); + string geometry; + char wall[CLENGTH] = ""; + geometry.append("\t\t<wall>\n"); + sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", + (w.GetPoint1().GetX()) * FAKTOR, + (w.GetPoint1().GetY()) * FAKTOR, + GetElevation(w.GetPoint1())*FAKTOR); + geometry.append(wall); + sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\" zPos=\"%.2f\"/>\n", + (w.GetPoint2().GetX()) * FAKTOR, + (w.GetPoint2().GetY()) * FAKTOR, + GetElevation(w.GetPoint2())*FAKTOR); + geometry.append(wall); + geometry.append("\t\t</wall>\n"); + + s.append(geometry); + //s.append(GetWall(j).Write()); + } + //add the subroom caption + Point pos = GetCentroid(); + char tmp[CLENGTH]; + sprintf(tmp, "\t\t<label centerX=\"%.2f\" centerY=\"%.2f\" centerZ=\"0\" text=\"%d\" color=\"100\" />\n" + , pos.GetX() * FAKTOR, pos.GetY() * FAKTOR, GetSubRoomID()); + s.append(tmp); + + //write the obstacles + for( unsigned int j=0;j<GetAllObstacles().size(); j++) { + s.append(GetAllObstacles()[j]->Write()); + } + + return s; +} + +string NormalSubRoom::WritePolyLine() const { + + string s; + char tmp[CLENGTH]; + + s.append("\t<Obstacle closed=\"1\" boundingbox=\"0\" class=\"1\">\n"); + for (unsigned int j = 0; j < _poly.size(); j++) { + sprintf(tmp, "\t\t<Vertex p_x = \"%.2lf\" p_y = \"%.2lf\"/>\n",_poly[j].GetX(),_poly[j].GetY()); + s.append(tmp); + } + s.append("\t</Obstacle>\n"); + + //write the obstacles + for( unsigned int j=0;j<GetAllObstacles().size(); j++) { + s.append(GetAllObstacles()[j]->Write()); + } + + return s; +} + +void NormalSubRoom::WriteToErrorLog() const { + Log->Write("\t\tNormal SubRoom:\n"); + for (int i = 0; i < GetNumberOfWalls(); i++) { + Wall w = GetWall(i); + w.WriteToErrorLog(); + } +} + +void NormalSubRoom::ConvertLineToPoly(vector<Line*> goals) { + vector<Line*> copy; + vector<Point> tmpPoly; + Point point; + Line* line; + // Alle Linienelemente in copy speichern + for (int i = 0; i < GetNumberOfWalls(); i++) { + copy.push_back(&_walls[i]); + } + // Transitions und Crossings sind in goal abgespeichert + copy.insert(copy.end(), goals.begin(), goals.end()); + + line = copy[0]; + tmpPoly.push_back(line->GetPoint1()); + point = line->GetPoint2(); + copy.erase(copy.begin()); + // Polygon aus allen Linen erzeugen + for (int i = 0; i < (int) copy.size(); i++) { + line = copy[i]; + if ((point - line->GetPoint1()).Norm() < J_TOLERANZ) { + tmpPoly.push_back(line->GetPoint1()); + point = line->GetPoint2(); + copy.erase(copy.begin() + i); + // von vorne suchen + i = -1; + } else if ((point - line->GetPoint2()).Norm() < J_TOLERANZ) { + tmpPoly.push_back(line->GetPoint2()); + point = line->GetPoint1(); + copy.erase(copy.begin() + i); + // von vorne suchen + i = -1; + } + } + if ((tmpPoly[0] - point).Norm() > J_TOLERANZ) { + char tmp[CLENGTH]; + sprintf(tmp, "ERROR: \tNormalSubRoom::ConvertLineToPoly(): SubRoom %d Room %d Anfangspunkt ungleich Endpunkt!!!\n" + "\t(%f, %f) != (%f, %f)\n", GetSubRoomID(), GetRoomID(), tmpPoly[0].GetX(), tmpPoly[0].GetY(), point.GetX(), + point.GetY()); + Log->Write(tmp); + sprintf(tmp, "ERROR: \tDistance between the points: %lf !!!\n", (tmpPoly[0] - point).Norm()); + Log->Write(tmp); + exit(EXIT_FAILURE); + } + _poly = tmpPoly; +} + + +// private Funktionen + +// 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); + +} + +// 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()))); +} + + +// 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; +} + +/************************************************************ + Stair + ************************************************************/ + +Stair::Stair() : NormalSubRoom() { + pUp = Point(); + pDown = Point(); +} + +Stair::Stair(const Stair & orig) : NormalSubRoom(orig) { + pUp = orig.GetUp(); + pDown = orig.GetDown(); +} + +Stair::~Stair() { +} + +// Setter-Funktionen + +void Stair::SetUp(const Point & p) { + pUp = p; +} + +void Stair::SetDown(const Point & p) { + pDown = p; +} + +// Getter-Funktionen + +const Point & Stair::GetUp() const { + return pUp; +} + +const Point & Stair::GetDown() const { + return pDown; +} + +string Stair::WriteSubRoom() const { + string s; + + for (int j = 0; j < GetNumberOfWalls(); j++) { + const Wall& w = GetWall(j); + + string 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]; + + s.append("\t<Obstacle closed=\"1\" boundingbox=\"0\" class=\"1\">\n"); + for (unsigned int j = 0; j < _poly.size(); j++) { + sprintf(tmp, "\t\t<Vertex p_x = \"%.2lf\" p_y = \"%.2lf\"/>\n",_poly[j].GetX(),_poly[j].GetY()); + s.append(tmp); + } + s.append("\t</Obstacle>\n"); + + //write the obstacles + for( unsigned int j=0;j<GetAllObstacles().size(); j++) { + s.append(GetAllObstacles()[j]->Write()); + } + + return s; +} +void Stair::WriteToErrorLog() const { + 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. + * Dabei liegt p2 IMMER in der Mitte und entspricht aktPoint + * */ +const Point* Stair::CheckCorner(const Point** otherPoint, const Point** aktPoint, const Point* nextPoint) { + + Point l1 = **otherPoint - **aktPoint; + Point l2 = *nextPoint - **aktPoint; + const Point* rueck = NULL; + // Punkte bilden eine Linie + if (fabs(fabs(l1.ScalarP(l2) / (l1.Norm() * l2.Norm())) - 1) < 0.1) { + *aktPoint = nextPoint; + } else // aktPoint/p2 ist eine Ecke + { + rueck = *aktPoint; + *otherPoint = *aktPoint; + *aktPoint = nextPoint; + } + return rueck; +} + +void Stair::ConvertLineToPoly(vector<Line*> goals) { + + //return NormalSubRoom::ConvertLineToPoly(goals); + + vector<Line*> copy; + vector<Point> orgPoly = vector<Point > (); + const Point* aktPoint; + const Point* otherPoint; + const Point* nextPoint; + const Point* firstAktPoint; + const Point* firstOtherPoint; + Line *nextLine; + + // Alle Linienelemente in copy speichern + for (int i = 0; i < GetNumberOfWalls(); i++) { + copy.push_back(&_walls[i]); + } + // Transitions und Crossings sind in goal abgespeichert + copy.insert(copy.end(), goals.begin(), goals.end()); + + aktPoint = ©[0]->GetPoint1(); + firstAktPoint = aktPoint; + otherPoint = ©[0]->GetPoint2(); + firstOtherPoint = otherPoint; + copy.erase(copy.begin()); + + // Polygon aus allen Linen erzeugen + for (int i = 0; i < (int) copy.size(); i++) { + nextLine = copy[i]; + nextPoint = NULL; + if ((*aktPoint - nextLine->GetPoint1()).Norm() < J_TOLERANZ) { + nextPoint = &nextLine->GetPoint2(); + } else if ((*aktPoint - nextLine->GetPoint2()).Norm() < J_TOLERANZ) { + nextPoint = &nextLine->GetPoint1(); + } + if (nextPoint != NULL) { + const Point* rueck = CheckCorner(&otherPoint, &aktPoint, nextPoint); + if (rueck != NULL) + orgPoly.push_back(*rueck); + copy.erase(copy.begin() + i); + i = -1; // von vorne suchen + } + } + if ((*aktPoint - *firstOtherPoint).Norm() < J_TOLERANZ) { + const Point* rueck = CheckCorner(&otherPoint, &aktPoint, firstAktPoint); + if (rueck != NULL) + orgPoly.push_back(*rueck); + } else { + char tmp[CLENGTH]; + double x1, y1, x2, y2; + x1 = firstOtherPoint->GetX(); + y1 = firstOtherPoint->GetY(); + x2 = aktPoint->GetX(); + y2 = aktPoint->GetY(); + sprintf(tmp, "ERROR: \tStair::ConvertLineToPoly(): SubRoom %d Room %d Anfangspunkt ungleich Endpunkt!!!\n" + "\t(%f, %f) != (%f, %f)\n", GetSubRoomID(), GetRoomID(), x1, y1, x2, y2); + Log->Write(tmp); + exit(EXIT_FAILURE); + } + + if (orgPoly.size() != 4) { + char tmp[CLENGTH]; + sprintf(tmp, "ERROR: \tStair::ConvertLineToPoly(): Stair %d Room %d ist kein Viereck!!!\n" + "Anzahl Ecken: %d\n", GetSubRoomID(), GetRoomID(), orgPoly.size()); + Log->Write(tmp); + exit(EXIT_FAILURE); + } + vector<Point> neuPoly = (orgPoly); + // ganz kleine Treppen (nur eine Stufe) nicht + if ((neuPoly[0] - neuPoly[1]).Norm() > 0.9 && (neuPoly[1] - neuPoly[2]).Norm() > 0.9) { + for (int i1 = 0; i1 < (int) orgPoly.size(); i1++) { + int i2 = (i1 + 1) % orgPoly.size(); + int i3 = (i2 + 1) % orgPoly.size(); + int i4 = (i3 + 1) % orgPoly.size(); + Point p1 = neuPoly[i1]; + Point p2 = neuPoly[i2]; + Point p3 = neuPoly[i3]; + Point p4 = neuPoly[i4]; + + Point l1 = p2 - p1; + Point l2 = p3 - p2; + + if (l1.Norm() < l2.Norm()) { + neuPoly[i2] = neuPoly[i2] + l1.Normalized() * 2 * J_EPS_GOAL; + l2 = p3 - p4; + neuPoly[i3] = neuPoly[i3] + l2.Normalized() * 2 * J_EPS_GOAL; + } + } + } + _poly = neuPoly; +} + +bool Stair::IsInSubRoom(const Point& ped) const { + bool rueck = false; + int N = (int) _poly.size(); + int sum = 0; + + for (int i = 0; i < N; i++) { + Line l = Line(_poly[i], _poly[(i + 1) % N]); + Point s = l.LotPoint(ped); + if (l.IsInLineSegment(s)) + sum++; + } + if (sum == 4) + rueck = true; + + return rueck; +} + +void SubRoom::SetType(const std::string& type) { + _type = type; +} + +const std::string& SubRoom::GetType() const { + return _type; +} + + +#ifdef _SIMULATOR + +void SubRoom::SetAllPedestrians(const vector<Pedestrian*>& peds) { + _peds = peds; +} + +void SubRoom::SetPedestrian(Pedestrian* ped, int index) { + if ((index >= 0) && (index < GetNumberOfPedestrians())) { + _peds[index] = ped; + } else { + Log->Write("ERROR: Wrong Index in SubRoom::SetPedestrian()"); + exit(0); + } +} + +bool SubRoom::IsInSubRoom(Pedestrian* ped) const { + //TODO: reference ? + Point pos = ped->GetPos(); + if (ped->GetExitLine()->DistTo(pos) <= J_EPS_GOAL) + return true; + else + return IsInSubRoom(pos); +} + + +int SubRoom::GetNumberOfPedestrians() const { + return _peds.size(); +} + +const vector<Pedestrian*>& SubRoom::GetAllPedestrians() const { + return _peds; +} + + + +Pedestrian* SubRoom::GetPedestrian(int index) const { + if ((index >= 0) && (index < (int) GetNumberOfPedestrians())) + return _peds[index]; + else { + Log->Write("ERROR: Wrong 'index' in SubRoom::GetPedestrian()"); + exit(0); + } +} + + +void SubRoom::AddPedestrian(Pedestrian* ped) { + _peds.push_back(ped); +} + + +void SubRoom::DeletePedestrian(int index) { + if ((index >= 0) && (index < (int) GetNumberOfPedestrians())) { + _peds.erase(_peds.begin() + index); + + } 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(); +} + +#endif // _SIMULATOR diff --git a/src/geometry/SubRoom.h b/src/geometry/SubRoom.h new file mode 100644 index 0000000000000000000000000000000000000000..5fc028546cc38131f328cbf5a53539700dba6b78 --- /dev/null +++ b/src/geometry/SubRoom.h @@ -0,0 +1,396 @@ +/** + * File: SubRoom.h + * + * Created on 8. October 2010, 10:56 + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#ifndef _SUBROOM_H +#define _SUBROOM_H + + +#include "Line.h" +#include "Wall.h" + +#include <vector> +#include <string> + +class Transition; +class Hline; +class Obstacle; +class Crossing; + +#ifdef _SIMULATOR + 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; + + +#ifdef _SIMULATOR + 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; + + /// 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; + +#endif + +}; + +/************************************************************ + NormalSubroom + ************************************************************/ + +class NormalSubRoom : public SubRoom { +private: + + ///@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(); + + std::string WriteSubRoom() const; + std::string WritePolyLine() 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; +}; + +#endif /* _SUBROOM_H */ + diff --git a/src/geometry/Transition.cpp b/src/geometry/Transition.cpp new file mode 100644 index 0000000000000000000000000000000000000000..590a7ff7b45eaa64271687594662f06519c6c407 --- /dev/null +++ b/src/geometry/Transition.cpp @@ -0,0 +1,182 @@ +/** + * File: Transition.cpp + * + * Created on 16. November 2010, 12:57 + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#include "Transition.h" +#include "Room.h" +#include "SubRoom.h" + +using namespace std; + +/************************************************************ + Transition (abgeleitet von Crossing) + ************************************************************/ + +Transition::Transition() : Crossing() { + _isOpen = true; + _room2 = NULL; +} + +Transition::~Transition() { +} + +// Setter-Funktionen + +void Transition::Close() { + _isOpen = false; +} + +void Transition::Open() { + _isOpen = true; +} + +void Transition::SetType(string type){ + _type=type; +} + +void Transition::SetRoom2(Room* r) { + _room2 = r; +} + +// Getter-Funktionen + +bool Transition::IsOpen() const { + return _isOpen; +} + + +Room* Transition::GetRoom2() const { + return _room2; +} + +string Transition::GetType() const { + return _type; +} +// Sonstiges + +// gibt den ANDEREN room != roomID zurück +Room* Transition::GetOtherRoom(int roomID) const { + if (GetRoom1()!=NULL && GetRoom1()->GetID() == roomID) { + return GetRoom2(); + } else if (GetRoom2()!=NULL && GetRoom2()->GetID() == roomID) { + return GetRoom1(); + } else { + char msg[CLENGTH]; + sprintf(msg,"ERROR: \tTransition::GetOtherRoom() wrong roomID [%d]",roomID); + Log->Write(msg); + exit(0); + } + +} +// virtuelle Funktionen + +// prüft ob Ausgang nach draußen +bool Transition::IsExit() const { + if(GetRoom1()!=NULL && _room2!=NULL) + return false; + else + return true; +} +// prüft, ob Transition in Raum mit roomID +bool Transition::IsInRoom(int roomID) const { + bool c1 = false; + bool c2 = false; + if (GetRoom1() != NULL && GetRoom1()->GetID() == roomID) + c1 = true; + if (GetRoom2() != NULL && GetRoom2()->GetID() == roomID) + c2 = true; + return c1 || c2; +} + +bool Transition::IsTransition() const { + return true; +} + + +/* gibt den ANDEREN Subroom mit GetRoomID() != roomID zurück + * subroomID wird hier nicht benötigt, aber in Crossings::GetOtherSubRoom() + * (virtuelle Funktion) */ +SubRoom* Transition::GetOtherSubRoom(int roomID, int subroomID) const { + if ((GetRoom1() != NULL) && (GetRoom1()->GetID() == roomID)) + return GetSubRoom2(); + else if ((GetRoom2() != NULL) && (GetRoom2()->GetID() == roomID)) + return GetSubRoom1(); + else { + char tmp[CLENGTH]; + sprintf(tmp,"ERROR: \tTransition::GetOtherSubRoom No exit found " + "on the other side\n ID=%hd, roomID=%hd, subroomID=%hd\n",GetUniqueID(),roomID,subroomID); + Log->Write(tmp); + exit(0); + } +} + +// 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); +} + +// 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; +} diff --git a/src/geometry/Transition.h b/src/geometry/Transition.h new file mode 100644 index 0000000000000000000000000000000000000000..e8fcb604e710ca20ebc292d3c0e739fc4284a43e --- /dev/null +++ b/src/geometry/Transition.h @@ -0,0 +1,101 @@ +/** + * File: Transition.h + * + * Created on 16. November 2010, 12:57 + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + */ + +#ifndef _TRANSITION_H +#define _TRANSITION_H + +#include "Crossing.h" +#include <string> + +class Room; +class Subroom; + +class Transition : public Crossing { +private: + Room* _room2; + bool _isOpen; + std::string _type; + +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); + + + /** + * Set/Get the type of the transition + * TODO: where is type defined? + */ + std::string GetType() const; + + /** + * Set/Get the second room associated with this transition. + * The first one is set in the crossing class. + */ + Room* GetRoom2() const; + + + /** + * @return the other room. + */ + Room* GetOtherRoom(int room_id) const; + + // virtual functions + virtual bool IsOpen() const; + virtual bool IsExit() const; + virtual bool IsTransition() const; + virtual bool IsInRoom(int roomID) const; + virtual SubRoom* GetOtherSubRoom(int roomID, int subroomID) const; + + + virtual void WriteToErrorLog() const; + virtual std::string WriteElement() const; // TraVisTo Ausgabe +}; + +#endif /* _TRANSITION_H */ + diff --git a/src/geometry/Wall.cpp b/src/geometry/Wall.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c0a56433941d45c26b6f52df15aca248152eab50 --- /dev/null +++ b/src/geometry/Wall.cpp @@ -0,0 +1,66 @@ +/** + * File: Wall.cpp + * + * Created on 16. November 2010, 12:55 + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#include "Wall.h" + +using namespace std; + +/************************************************************ + Wall + ************************************************************/ + +Wall::Wall() : Line() { +} + +Wall::Wall(const Point& p1, const Point& p2) : Line(p1, p2) { + +} + +Wall::Wall(const Wall& orig) : Line(orig) { +} + +void Wall::WriteToErrorLog() const { + char tmp[CLENGTH]; + sprintf(tmp, "\t\tWALL: (%f, %f) -- (%f, %f)\n", GetPoint1().GetX(), + GetPoint1().GetY(), GetPoint2().GetX(), GetPoint2().GetY()); + Log->Write(tmp); +} + +string Wall::Write() const { + string geometry; + char wall[500] = ""; + geometry.append("\t\t<wall>\n"); + sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n", + (GetPoint1().GetX()) * FAKTOR, + (GetPoint1().GetY()) * FAKTOR); + geometry.append(wall); + sprintf(wall, "\t\t\t<point xPos=\"%.2f\" yPos=\"%.2f\"/>\n", + (GetPoint2().GetX()) * FAKTOR, + (GetPoint2().GetY()) * FAKTOR); + geometry.append(wall); + geometry.append("\t\t</wall>\n"); + return geometry; +} diff --git a/src/geometry/Wall.h b/src/geometry/Wall.h new file mode 100644 index 0000000000000000000000000000000000000000..85e2ba51ee11a6bd166f5f0f7c7d5e79f93e3a0c --- /dev/null +++ b/src/geometry/Wall.h @@ -0,0 +1,53 @@ +/** + * File: Wall.h + * + * Created on 16. November 2010, 12:55 + * + * @section LICENSE + * This file is part of JuPedSim. + * + * JuPedSim is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * JuPedSim is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. + * + * @section DESCRIPTION + * + * + * + */ + +#ifndef _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); + + /** + * Debug output from the object + */ + void WriteToErrorLog() const; + + /** + * @return a nicely formated string of the object + */ + virtual std::string Write() const; +}; + + +#endif /* _WALL_H */ + diff --git a/src/geometry/jul/Building.cpp b/src/geometry/jul/Building.cpp deleted file mode 100644 index 5fac31f8b2322eb643da286da35e1ffde64dc9e3..0000000000000000000000000000000000000000 --- a/src/geometry/jul/Building.cpp +++ /dev/null @@ -1,350 +0,0 @@ -/* - * File: Building.cpp - * Author: andrea - * - * Created on 1. Oktober 2010, 09:25 - */ - -#include "Building.h" - -/************************************************************ - Konstruktoren - ************************************************************/ - -Building::Building() { - pCaption = "no caption"; - pRooms = vector<Room > (); -} - -Building::Building(const Building& orig) { - pCaption = orig.GetCaption(); - pRooms = orig.GetAllRooms(); -} - -Building::~Building() { - if (pRooms.size() > 0) pRooms.clear(); -} - -/************************************************************* - Setter-Funktionen - ************************************************************/ -void Building::SetCaption(string s) { - pCaption = s; -} - -void Building::SetAllRooms(const vector<Room>& rooms) { - pRooms = rooms; -} - -void Building::SetRoom(const Room& room, int index) { - if ((index >= 0) && (index < (int) pRooms.size())) { - pRooms[index] = room; - } else { - printf("ERROR: \tWrong Index in CBuilding.SetRoom()"); - exit(0); - } -} - -/************************************************************* - Getter-Funktionen - ************************************************************/ - -string Building::GetCaption() const { - return pCaption; -} - -const vector<Room>& Building::GetAllRooms() const { - return pRooms; -} - -const Room& Building::GetRoom(int index) const { - if ((index >= 0) && (index < (int) pRooms.size())) { - return pRooms[index]; - } else { - printf("ERROR: Wrong 'index'=%d in CBuiling::GetRoom()\n",index); - exit(0); - } -} - -/************************************************************* - Sonstiges - ************************************************************/ -void Building::InitGeometry() { - for (int i = 0; i < pRooms.size(); i++) { - Room room = GetRoom(i); - vector<Transition> trans = room.GetAllTransitions(); - // alle Tueren öffnen - for (int j = 0; j < trans.size(); j++) { - trans[j].Open(); - room.SetTransition(trans[j], j); - } - // Polygone berechnen - room.ConvertLineToPoly(); - SetRoom(room, i); - } -} - -void Building::AddRoom(const Room& room) { - pRooms.push_back(room); -} - -int Building::RoomIndexForThisID(int ID) const { - int i; - for (i = 0; i < pRooms.size(); i++) { - if (pRooms[i].GetRoomID() == ID) - break; - } - if (i == pRooms.size()) { - printf("ERROR: \tBuilding::RoomIndexForThisID() can not find ID!"); - exit(0); - } - return i; -} - -/************************************************************* - Ein-Ausgabe - ************************************************************/ - -void Building::LoadFromFile(string filename) { - ifstream buildingfile; - string line; - - // Datei oeffnen - buildingfile.open(filename.c_str(), fstream::in); - if (!buildingfile) { - printf("ERROR: \tCannot load building file: %s", filename.c_str()); - exit(0); - } else { - int i = 0; - while (getline(buildingfile, line)) { - i++; // Zeienindex zum debuggen, nach jedem getline() erhöhen - if (line.find("<header>") != string::npos) { - LoadHeader(&buildingfile, &i); - } else if (line.find("<rooms>") != string::npos) { - LoadRooms(&buildingfile, &i); - } else if (line.find("<transitions>") != string::npos) { - LoadTransitions(&buildingfile, &i); - } else { - char tmp[100]; - sprintf(tmp, "ERROR: \tWrong object in building file: [%s] line %d ", line.c_str(), i); - printf("%s",tmp); - exit(0); - } - } - buildingfile.close(); - buildingfile.clear(); - } -} - -void Building::WriteToErrorLog() const { - printf("GEOMETRY: "); - for (int i = 0; i < pRooms.size(); i++) { - Room r = GetRoom(i); - r.WriteToErrorLog(); - } - printf("\n"); -} - -/************************************************************* - private Funktionen - ************************************************************/ -void Building::LoadHeader(ifstream* buildingfile, int* i) { - string line; - - getline(*buildingfile, line); - (*i)++; - while (line.find("</header>") == string::npos) { - if (line.find("caption") != string::npos) { - istringstream iss(line, istringstream::in); - string tmp; // Schlüsselwort, hier: "caption" - iss >> tmp >> pCaption; - } else if (line.find("version") != string::npos) { - istringstream iss(line, istringstream::in); - string tmp; // Schlüsselwort, hier: "version" - double version; - iss >> tmp >> version; - if (version != 0.1) { - char tmp[100]; - sprintf(tmp, "ERROR: \tneue Version im Geometrieformat!!! %f != %f", version, VERSION); - printf(tmp); - exit(0); - } - } else { - char tmp[100]; - sprintf(tmp, "ERROR: \tWrong object in building file <header>: [%s] line %d " - , line.c_str(), *i); - printf("%s", tmp); - exit(0); - } - getline(*buildingfile, line); - (*i)++; - } -} - -void Building::LoadRooms(ifstream* buildingfile, int* i) { - string line; - getline(*buildingfile, line); - (*i)++; - int elements = 0; - while (line.find("</rooms>") == string::npos) { - if (line.find("elements") != string::npos) { - istringstream iss(line, istringstream::in); - string tmp; // Schlüsselwort - iss >> tmp >> elements; - } else if (line.find("<room>") != string::npos) { - LoadRoom(buildingfile, i); - } else { - char tmp[100]; - sprintf(tmp, "ERROR: \tWrong object in building file <rooms>: [%s] line %d " - , line.c_str(), i); - printf("%s", tmp); - exit(0); - } - getline(*buildingfile, line); - (*i)++; - } - if (elements != pRooms.size()) { - char tmp[100]; - sprintf(tmp, "ERROR: \tWrong number of rooms: %d != %d", elements, pRooms.size()); - printf("%s", tmp); - exit(0); - } - -} - -void Building::LoadRoom(ifstream* buildingfile, int* i) { - string line; - getline(*buildingfile, line); - (*i)++; - Room room = Room(); - while (line.find("</room>") == string::npos) { - if (line.find("caption") != string::npos) { - istringstream iss(line, istringstream::in); - string tmp, caption; // Schlüsselwort, hier: "caption" - iss >> tmp >> caption; - room.SetCaption(caption); - } else if (line.find("index") != string::npos) { - istringstream iss(line, istringstream::in); - string tmp; // Schlüsselwort - int ID; - iss >> tmp >> ID; - room.SetRoomID(ID); - } else if (line.find("zpos") != string::npos) { - istringstream iss(line, istringstream::in); - string tmp; // Schlüsselwort - int zpos; - iss >> tmp >> zpos; - room.SetZPos(zpos); - } else if (line.find("<contdata>") != string::npos) { - room.LoadWalls(buildingfile, i); - } else { - char tmp[100]; - sprintf(tmp, "ERROR: \tWrong object in building file <room> :" - "[%s] line %d ", line.c_str(), i); - printf("%s", tmp); - exit(0); - } - getline(*buildingfile, line); - (*i)++; - } - AddRoom(room); -} - -void Building::LoadTransitions(ifstream* buildingfile, int* i) { - string line; - getline(*buildingfile, line); - (*i)++; - int elements = 0; - int anz = 0; - while (line.find("</transitions>") == string::npos) { - if (line.find("elements") != string::npos) { - istringstream iss(line, istringstream::in); - string tmp; // Schlüsselwort - iss >> tmp >> elements; - } else if (line.find("<transition>") != string::npos) { - anz++; - LoadTransition(buildingfile, i); - } else { - char tmp[100]; - sprintf(tmp, "ERROR: \tWrong object in building file <transition>: [%s] line %d ", - line.c_str(), i); - printf("%s", tmp); - exit(0); - } - getline(*buildingfile, line); - (*i)++; - } - if (elements != anz) { - char tmp[100]; - sprintf(tmp, "ERROR: \tWrong number of rooms: %d != %d", elements, pRooms.size()); - printf("%s", tmp); - exit(0); - } -} - -void Building::LoadTransition(ifstream* buildingfile, int* i) { - string line; - getline(*buildingfile, line); - Transition t; - (*i)++; - while (line.find("</transition>") == string::npos) { - if (line.find("index") != string::npos) { - istringstream iss(line, istringstream::in); - string tmp; // Schlüsselwort - int ID; - iss >> tmp >> ID; - t.SetID(ID); - } else if (line.find("caption") != string::npos) { - istringstream iss(line, istringstream::in); - string tmp, caption; - iss >> tmp >> caption; - t.SetCaption(caption); - } else if (line.find("trans") != string::npos) { - istringstream iss(line, istringstream::in); - string tmp; - float x1, y1, x2, y2; - iss >> tmp >> x1 >> y1 >> x2 >> y2; - t.SetLine(Line(CPoint(x1, y1), CPoint(x2, y2))); - } else if (line.find("room1") != string::npos) { - istringstream iss(line, istringstream::in); - string tmp; - int room1; - iss >> tmp >> room1; - t.SetRoom1(room1); - } else if (line.find("room2") != string::npos) { - stringstream iss(line, istringstream::in); - string tmp; - int room2; - iss >> tmp >> room2; - t.SetRoom2(room2); - } else { - char tmp[100]; - sprintf(tmp, "ERROR: \tWrong object in building file <transition> <transition>: [%s] line %d ", - line.c_str(), i); - printf("%s", tmp); - exit(0); - } - getline(*buildingfile, line); - (*i)++; - } - int ID1 = t.GetRoom1(); - int ID2 = t.GetRoom2(); - if (ID1 == ID2) { // spaeter vielleicht Sondertüren einfügen - if(ID1 >=0){ - Room r = GetRoom(ID1); - r.AddTransition(t); - SetRoom(r, ID1); - } - } else { // Transition zu beiden Räumen hinzufügen - if (ID1 != -1) { // -1 bedeutet Ausgang - Room r = GetRoom(ID1); - r.AddTransition(t); - SetRoom(r, ID1); - } - if (ID2 != -1) { - Room r = GetRoom(ID2); - r.AddTransition(t); - SetRoom(r, ID2); - } - } -} diff --git a/src/geometry/jul/Building.h b/src/geometry/jul/Building.h deleted file mode 100644 index 41b394a37aa8fe03e9daa2e6305e5ad78e45ac4f..0000000000000000000000000000000000000000 --- a/src/geometry/jul/Building.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * File: Building.h - * Author: andrea - * - * Created on 1. Oktober 2010, 09:25 - */ - -#ifndef _BUILDING_H -#define _BUILDING_H - -#include <string> -#include <vector> -#include <fstream> -#include <sstream> -using namespace std; - -#include "Room.h" -#include "Macros.h" - -class Building { -private: - string pCaption; // Name des Projekts - vector<Room> pRooms; // Liste der Räume - - // wird nur innerhalb von Building benötigt - void LoadHeader(ifstream* buildingfile, int* i); - void LoadRooms(ifstream* buildingfile, int* i); - void LoadRoom(ifstream* buildingfile, int* i); - - void LoadTransitions(ifstream* buildingfile, int* i); - void LoadTransition(ifstream* buildingfile, int* i); -public: - Building(); - Building(const Building& orig); - virtual ~Building(); - - // Setter -Funktionen - void SetCaption(string s); - void SetAllRooms(const vector<Room>& rooms); - void SetRoom(const Room& room, int index); - - // Getter - Funktionen - string GetCaption() const; - const vector<Room>& GetAllRooms() const; - const Room& GetRoom(int index) const; // Gibt Raum der Nummer "index" zurueck - - // Sonstiges - void InitGeometry(); - void AddRoom(const Room& room); - int RoomIndexForThisID(int ID) const; - - // Ein-Ausgabe - void LoadFromFile(string filename); // Laedt Geometrie-Datei - void WriteToErrorLog() const; -}; - -#endif /* _BUILDING_H */ - diff --git a/src/geometry/jul/CPoint.cpp b/src/geometry/jul/CPoint.cpp deleted file mode 100644 index 973fe06b3108263225326859c203ce7508a493c9..0000000000000000000000000000000000000000 --- a/src/geometry/jul/CPoint.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * File: CPoint.cpp - * Author: andrea - * - * Created on 30. September 2010, 09:21 - */ - -#include "CPoint.h" - -/************************************************************ - Konstruktoren - ************************************************************/ -CPoint::CPoint() { - pX = 0.0; - pY = 0.0; -} - -CPoint::CPoint(float x, float y) { - pX = x; - pY = y; -} - -CPoint::CPoint(const CPoint& orig) { - pX = orig.GetX(); - pY = orig.GetY(); -} - -CPoint::~CPoint() { -} - -/************************************************************* - Setter-Funktionen - ************************************************************/ - -void CPoint::SetX(float x) { - pX = x; -} - -void CPoint::SetY(float y) { - pY = y; -} - -/************************************************************* - Getter-Funktionen - ************************************************************/ - -float CPoint::GetX() const { - return pX; -} - -float CPoint::GetY() const { - return pY; -} - -/************************************************************* - Sonstige Funktionen - ************************************************************/ - -// Norm des Vektors - -float CPoint::Norm() const { - return sqrt(pX * pX + pY * pY); -} - -// gibt den normierten Vector zurueck - -CPoint CPoint::Normalized() const { - if (Norm() != 0) - return (CPoint(pX, pY) / Norm()); - else return CPoint(0.0, 0.0); -} - -// Skalarprodukt zweier Vektoren - -float CPoint::ScalarP(const CPoint& v) const { - return pX * v.GetX() + pY * v.GetY(); -} - -// rotiert Vektor um den Winkel theta - -CPoint CPoint::Rotate(float theta) const { - float s = sin(theta); - float c = cos(theta); - return CPoint(pX * c - pY*s, pX * s + pY * c); -} - -// Transformiert die Koordinaten in Koordinaten der Ellipse -// dazu verschieben des Koordinaten Ursprungs in Center und anschliessend drehen um phi -// alle Pnktte müssen in "normale" Koordinaten gegeben sein - -CPoint CPoint::CoordTransToEllipse(const CPoint& center, float phi) const { - CPoint p = CPoint(pX, pY); - return (p - center).Rotate(-phi); -} - -// Transformiert zurueck ins urspruengliche Koord.system - -CPoint CPoint::CoordTransToCart(const CPoint& center, float phi) const { - CPoint p = CPoint(pX, pY); - return (p.Rotate(phi) + center); -} - -/************************************************************* - überladene Operatoren - ************************************************************/ - -// Addiert zwei Vektoren - -const CPoint CPoint::operator+(const CPoint& p) const { - return CPoint(pX + p.GetX(), pY + p.GetY()); -} - -// Subtrahiert zwei Vektoren - -const CPoint CPoint::operator-(const CPoint& p) const { - return CPoint(pX - p.GetX(), pY - p.GetY()); -} - -// Vergleicht zwei Punkte/Vektoren komponentweise - -bool CPoint::operator==(const CPoint& p) const { - return (pX == p.GetX() && pY == p.GetY()); -} - -// Vergleicht zwei Punkte/Vektoren komponentweise - -bool CPoint::operator!=(const CPoint& p) const { - return (pX != p.GetX() || pY != p.GetY()); -} - - -// Multipliziert einen Vektor mit einem Skalar - -CPoint operator*(const CPoint& p, float f) { - return CPoint(p.GetX() * f, p.GetY() * f); -} - -// Dividiert einen Vektor durch einen Skalar - -CPoint operator/(const CPoint& p, float f) { - return CPoint(p.GetX() / f, p.GetY() / f); -} diff --git a/src/geometry/jul/CPoint.h b/src/geometry/jul/CPoint.h deleted file mode 100644 index 1e23775b1c0e3e6b92c10490e27b6318e0eb740b..0000000000000000000000000000000000000000 --- a/src/geometry/jul/CPoint.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * File: CPoint.h - * Author: andrea - * - * Created on 30. September 2010, 09:21 - */ - -#ifndef _POINT_H -#define _POINT_H - -#include <cmath> - -class CPoint { -private: - float pX; - float pY; - -public: - CPoint(); - CPoint(float x, float y); - CPoint(const CPoint& orig); - virtual ~CPoint(); - - // Setter-Funktionen - void SetX(float x); // setzt x-Koordinate - void SetY(float y); // setzt y-Koordinate - - // Getter-Funktionen - float GetX() const; // gibt x-Koordinate zurück - float GetY() const; // gibt y-Koordinate zurück - - // Sonstiges - float Norm() const; // Norm des Vektors - CPoint Normalized() const; - float ScalarP(const CPoint& v) const; // Skalarprodukt zweier Vektoren - CPoint Rotate(float theta) const; // rotiert Vektor um den Winkel theta - CPoint CoordTransToEllipse(const CPoint& center, float phi) const; // Verschiebung und Drehung - CPoint CoordTransToCart(const CPoint& center, float phi) const; // Verschiebung und Drehung - - const CPoint operator+(const CPoint& p) const; // Addiert zwei Vektoren - const CPoint operator-(const CPoint& p) const; // Subtrahiert zwei Vektoren - bool operator==(const CPoint& p) const; // Vergleicht zwei Punkte/Vektoren komponentweise - bool operator!=(const CPoint& p) const; // Vergleicht zwei Punkte/Vektoren komponentweise -}; - - -// Operatoren mit float -CPoint operator*(const CPoint& p, const float f); -CPoint operator/(const CPoint& p, const float f); - -#endif /* _POINT_H */ - diff --git a/src/geometry/jul/Line.cpp b/src/geometry/jul/Line.cpp deleted file mode 100644 index 1eebb2e3ddc5c26fea35a9a04b6c96ce2d2cd86f..0000000000000000000000000000000000000000 --- a/src/geometry/jul/Line.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * File: Line.cpp - * Author: andrea - * - * Created on 30. September 2010, 09:40 - */ - -#include "Line.h" - -/************************************************************ - Konstruktoren - ************************************************************/ -Line::Line() { - SetPoint1(CPoint()); //Defaul-Constructor ist (0.0,0.0) - SetPoint2(CPoint()); -} - -Line::Line(const CPoint& p1, const CPoint& p2) { - SetPoint1(p1); - SetPoint2(p2); -} - -Line::Line(const Line& orig) { - pPoint1 = orig.GetPoint1(); - pPoint2 = orig.GetPoint2(); -} - -Line::~Line() { -} - -/************************************************************* - Setter-Funktionen - ************************************************************/ -void Line::SetPoint1(const CPoint& p) { - pPoint1 = p; -} - -void Line::SetPoint2(const CPoint& p) { - pPoint2 = p; -} - -/************************************************************* - Getter-Funktionen - ************************************************************/ -const CPoint& Line::GetPoint1(void) const { - return pPoint1; -} - -const CPoint& Line::GetPoint2(void) const { - return pPoint2; -} - -/************************************************************* - Sonstige Funktionen - ************************************************************/ -CPoint Line::NormalVec() const { - float nx, ny, norm; - CPoint 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); - nx /= norm; - ny /= norm; - } - return CPoint(nx, ny); -} - -float Line::NormalComp(const CPoint& v) const { - CPoint diff = GetPoint2() - GetPoint1(); - CPoint u, x; - float nu = diff.Norm(); - - if (nu < 0.0001) { - printf("ERROR: \tCLine::NormalComp(): normal_vector length==0\nstop\n"); - exit(0); - } - u = diff / nu; - - if (u.GetX() < 0.0001) - x = CPoint(1.0, 0.0); - else - x = CPoint(-u.GetY() / u.GetX(), 1.0); - - return fabs(v.ScalarP(x)); //sqrt(v.x*v.x+v.y*v.y); // -} - -CPoint Line::ShortestPoint(const CPoint& p) const { - CPoint r = GetPoint1(); - CPoint s = GetPoint2(); - CPoint t = r - s; - CPoint tmp; - float lambda; - - tmp = p - s; - lambda = tmp.ScalarP(t) / t.ScalarP(t); - CPoint f = s + t*lambda; - - /* Prüfen ob Punkt in der Linie,sonst entsprechenden Eckpunkt zurückgeben */ - if (lambda < 0) - f = s; - if (lambda > 1) - f = r; - - return f; -} - -bool Line::IsInLine(const CPoint& p) const { - float ax, ay, bx, by, px, py; - CPoint a = GetPoint1(); - CPoint b = GetPoint2(); - float lambda; - ax = a.GetX(); - ay = a.GetY(); - bx = b.GetX(); - by = b.GetY(); - px = p.GetX(); - py = p.GetY(); - if (ax != bx) - lambda = (px - ax) / (bx - ax); - else if (ay != by) - lambda = (py - ay) / (by - ay); - else { - printf("ERROR: \tIsInLine: Endpunkt = Startpunkt!!!"); - exit(0); - } - return (0 <= lambda) && (lambda <= 1); -} - -float Line::DistTo(const CPoint& p) const { - return (p - ShortestPoint(p)).Norm(); -} - -/************************************************************* - Ausgabe Funktionen - ************************************************************/ - diff --git a/src/geometry/jul/Line.h b/src/geometry/jul/Line.h deleted file mode 100644 index d276adeca7c414d770edbf43a082d665ce768bd1..0000000000000000000000000000000000000000 --- a/src/geometry/jul/Line.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * File: Line.h - * Author: andrea - * - * Created on 30. September 2010, 09:40 - */ - -#ifndef _LINE_H -#define _LINE_H - -#include <stdio.h> -#include <stdlib.h> - - -#include "CPoint.h" - - -class Line { -private: - CPoint pPoint1; // (Koordinaten des ersten Punkts) - CPoint pPoint2; // (Koordinaten des zweiten Punkts) -public: - Line(); - Line(const CPoint& p1, const CPoint& p2); - Line(const Line& orig); - virtual ~Line(); - - // Setter -Funktionen - void SetPoint1(const CPoint& p); // setzt die Anfangskoordinaten - void SetPoint2(const CPoint& p); // setzt die Endkoordinaten - - // Getter - Funktionen - const CPoint& GetPoint1(void) const; // gibt die Koordinaten des Anfangspunkts zurück - const CPoint& GetPoint2(void) const; // gibt die Koordinaten des Endpunkts zurück - - // Sonstiges - CPoint NormalVec() const; /* Normalen_Vector zu Cline*/ - float NormalComp(const CPoint& v) const; /* Normale Komponente von v auf l */ - CPoint ShortestPoint(const CPoint& p) const; /* Punkt auf Cline mit kürzstem Abstand zu p */ - bool IsInLine(const CPoint& p) const; /* Prüft, ob der p in der Wand ist oder außerhalb */ - float DistTo(const CPoint& p) const; - - //Ausgabe - -}; - -#endif /* _LINE_H */ - diff --git a/src/geometry/jul/Macros.h b/src/geometry/jul/Macros.h deleted file mode 100644 index 6bea206ea20e1cec6b0ad9043794bc38848fb99a..0000000000000000000000000000000000000000 --- a/src/geometry/jul/Macros.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * File: Macros.h - * Author: andrea - * - * Created on 16. Juni 2010, 16:59 - */ - -#ifndef _MACROS_H -#define _MACROS_H - -// Genauigkeit -#define EPS 0.001 -// zur Versionskontrolle beim Geometrieformat -#define VERSION 0.10 -#define TOLERANZ 0.10 // [m] Toleranz beim erstellen der Linien - - -#endif /* _MACROS_H */ - diff --git a/src/geometry/jul/Room.cpp b/src/geometry/jul/Room.cpp deleted file mode 100644 index ce6669920b03138766e874386bc87b18d9e616b6..0000000000000000000000000000000000000000 --- a/src/geometry/jul/Room.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/* - * File: Room.cpp - * Author: andrea - * - * Created on 30. September 2010, 11:58 - */ - -#include <vector> - -#include "Room.h" -#include "Transition.h" - -/************************************************************ - Konstruktoren - ************************************************************/ - -Room::Room() { - pRoomID = -1; - pCaption = "no room caption"; - pZPos = -1; - pWalls = vector<Wall > (); - pTransitions = vector<Transition > (); - pPoly = vector<CPoint > (); -} - -Room::Room(const Room& orig) { - pRoomID = orig.GetRoomID(); - pCaption = orig.GetCaption(); - pZPos = orig.GetZPos(); - pWalls = orig.GetAllWalls(); - pTransitions = orig.GetAllTransitions(); - pPoly = orig.GetPolygon(); -} - -Room::~Room() { - if (pWalls.size() > 0) pWalls.clear(); - if (pTransitions.size() > 0) pTransitions.clear(); - if (pPoly.size() > 0) pPoly.clear(); -} - -/************************************************************* - Setter-Funktionen - ************************************************************/ -void Room::SetRoomID(int ID) { - pRoomID = ID; -} - -void Room::SetCaption(string s) { - pCaption = s; -} - -void Room::SetZPos(int z) { - pZPos = z; -} - -void Room::SetAllWalls(const vector<Wall>& walls) { - pWalls = walls; -} - -void Room::SetWall(const Wall& wall, int index) { - if ((index >= 0) && (index < (int) pWalls.size())) { - pWalls[index] = wall; - } else { - printf("ERROR: Wrong Index in CRoom::SetWall()"); - exit(0); - } -} - -void Room::SetAllTransitions(const vector<Transition>& transitions) { - pTransitions = transitions; -} - -void Room::SetTransition(const Transition& transition, int index) { - if ((index >= 0) && (index < (int) pTransitions.size())) { - pTransitions[index] = transition; - } else { - printf("ERROR: Wrong Index in CRoom::SetTransition()"); - exit(0); - } -} - -void Room::SetPolygon(const vector<CPoint>& poly) { - pPoly = poly; -} - - - -/************************************************************* - Getter-Funktionen - ************************************************************/ -int Room::GetRoomID() const { - return pRoomID; -} - -string Room::GetCaption() const { - return pCaption; -} - -int Room::GetZPos() const { - return pZPos; -} - -const vector<Wall>& Room::GetAllWalls() const { - return pWalls; -} - -const Wall Room::GetWall(int index) const { - if ((index >= 0) && (index < (int) pWalls.size())) - return pWalls[index]; - else { - printf("ERROR: Wrong 'index' in CRoom::GetWall()"); - exit(0); - } - -} - -const vector<Transition> Room::GetAllTransitions() const { - return pTransitions; -} - -const Transition Room::GetTransition(int index) const { - if ((index >= 0) && (index < (int) pTransitions.size())) - return pTransitions[index]; - else { - printf("ERROR: Wrong 'index' in CRoom::GetTransition()"); - exit(0); - } -} - -const vector<CPoint>& Room::GetPolygon() const { - return pPoly; -} - - -/************************************************************* - Sonstige Funktionen - ************************************************************/ - -void Room::AddWall(const Wall& w) { - pWalls.push_back(w); -} - -void Room::DeleteWall(int index) { - if ((index >= 0) && (index < (int) pWalls.size())) - pWalls.erase(pWalls.begin() + index); - else { - printf("ERROR: Wrong Index in CRoom::DeleteWall()"); - exit(0); - } -} - -void Room::AddTransition(const Transition& trans) { - pTransitions.push_back(trans); -} - -void Room::DeleteTransition(int index) { - if ((index >= 0) && (index < (int) pTransitions.size())) - pTransitions.erase(pTransitions.begin() + index); - else { - printf("ERROR: Wrong Index in CRoom::DeleteTransition()"); - exit(0); - } -} - -void Room::CloseTransition(int index) { - Transition tmp = GetTransition(index); - if (tmp.GetIsOpen()) { - tmp.Close(); - SetTransition(tmp, index); - } else { - printf("ERROR: Wrong Index in CRoom::CloseTransition() Transition is closed!!!"); - exit(0); - } -} - - -void Room::ConvertLineToPoly() { - vector<Line> copy; - CPoint point; - Line line; - - // Alle Linienelemente in copy speichern Wände und Transitions - for (int i = 0; i < pWalls.size(); i++) { - copy.push_back(pWalls[i].GetLine()); - } - for (int i = 0; i < pTransitions.size(); i++) { - copy.push_back(pTransitions[i].GetLine()); - } - - line = copy[0]; - pPoly.push_back(line.GetPoint1()); - point = line.GetPoint2(); - copy.erase(copy.begin()); - - for (int i = 0; i < (int) copy.size(); i++) { - line = copy[i]; - if ((point - line.GetPoint1()).Norm()< TOLERANZ) { - pPoly.push_back(line.GetPoint1()); - point = line.GetPoint2(); - copy.erase(copy.begin() + i); - // von vorne suchen - i = -1; - } else if ((point - line.GetPoint2()).Norm()< TOLERANZ) { - pPoly.push_back(line.GetPoint2()); - point = line.GetPoint1(); - copy.erase(copy.begin() + i); - // von vorne suchen - i = -1; - } - } - if ((pPoly[0] - point).Norm()>TOLERANZ) { - char tmp[100]; - sprintf(tmp,"ERROR: \tRoom::ConvertLineToPoly(): Raum %d Anfangspunkt ungleich Endpunkt!!!\n" - "(%f, %f) != (%f, %f)\n", GetRoomID(), pPoly[0].GetX(), pPoly[0].GetY(), point.GetX(), - point.GetY()); - printf("%s", tmp); - exit(0); - } -} - - -bool Room::IsStart() const { - return pCaption.find("start") != string::npos; -} - -bool Room::IsExit() const { - return pCaption.find("exit") != string::npos; -} - -CPoint Room::GetCentre() const { - //This will only work for orthogonally orientated rectangular rooms - vector<float> xs; - vector<float> ys; - vector<float>::iterator xmin, xmax, ymin, ymax; - CPoint mid; - - for (int i = 0; i < pPoly.size(); i++) { - xs.push_back(pPoly[i].GetX()); - ys.push_back(pPoly[i].GetY()); - } - xmin = min_element(xs.begin(), xs.end()); - xmax = max_element(xs.begin(), xs.end()); - ymin = min_element(ys.begin(), ys.end()); - ymax = max_element(ys.begin(), ys.end()); - mid.SetX((*xmin + *xmax) / 2); - mid.SetY((*ymin + *ymax) / 2); - return mid; - - -} - - - -/************************************************************* - Ein-Ausgabe - ************************************************************/ -void Room::LoadWalls(ifstream* buildingfile, int* i) { - string line; - getline(*buildingfile, line); - (*i)++; - int elements; - while (line.find("</contdata>") == string::npos) { - if (line.find("<elements>") != string::npos) { - getline(*buildingfile, line); - (*i)++; - while (line.find("</elements>") == string::npos) { - if (line.find("wall") != string::npos) { - Wall wall = Wall(); - istringstream iss(line, istringstream::in); - string tmp; // Schlüsselwort - float x1, y1, x2, y2; - iss >> tmp >> x1>> y1 >> x2 >> y2; - wall.SetLine(Line(CPoint(x1, y1), CPoint(x2, y2))); - AddWall(wall); - } else { - char tmp[100]; - sprintf(tmp, "ERROR: \tWrong object in building file <room> " - "<contdata> <element>: [%s] line %d ", line.c_str(), i); - printf("%s", tmp); - exit(0); - } - getline(*buildingfile, line); - (*i)++; - } - } else if (line.find("elements") != string::npos) { - istringstream iss(line, istringstream::in); - string tmp; // Schlüsselwort - iss >> tmp >> elements; - } else { - char tmp[100]; - sprintf(tmp, "ERROR: \tWrong object in building file <room> <contdata>:" - "[%s] line %d ", line.c_str(), i); - printf("%s", tmp); - exit(0); - } - getline(*buildingfile, line); - (*i)++; - } - if (elements != pWalls.size()) { - char tmp[100]; - sprintf(tmp, "ERROR: \tWrong number of rooms: %d != %d", elements, pWalls.size()); - printf("%s", tmp); - exit(0); - } -} - -void Room::WriteToErrorLog() const { - char tmp[300]; - string s; - sprintf(tmp, "\tRaum: %d [%s]:", pRoomID, pCaption.c_str()); - s.append(tmp); - printf("%s", tmp); - // Wände - for (int i = 0; i < pWalls.size(); i++) { - Wall w = GetWall(i); - w.WriteToErrorLog(); - } - //Übergänge - for (int i = 0; i < pTransitions.size(); i++) { - Transition t = GetTransition(i); - t.WriteToErrorLog(); - } -} diff --git a/src/geometry/jul/Room.h b/src/geometry/jul/Room.h deleted file mode 100644 index e5d23350552e7c1b202b451252f5ad771b241cf4..0000000000000000000000000000000000000000 --- a/src/geometry/jul/Room.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * File: Room.h - * Author: andrea - * - * Created on 30. September 2010, 11:58 - */ - -#ifndef _ROOM_H -#define _ROOM_H - -#include <stdio.h> - - -#include <string> -#include <algorithm> -#include <fstream> -#include <sstream> -using namespace std; - -#include "Transition.h" -#include "Wall.h" -#include "Macros.h" - -class Room { -private: - int pRoomID; // Raumindex - string pCaption; // Raumname - int pZPos; // Hoehenindex, kontinuierlich vielleicht unnötig? - vector<Wall> pWalls; // Wände - vector<Transition> pTransitions; // Ausgänge - vector<CPoint> pPoly; // Alle Eckpunkte des Raums als Polygon - -public: - Room(); - Room(const Room& orig); - virtual ~Room(); - - // Setter -Funktionen - void SetRoomID(int ID); - void SetCaption(string s); - void SetZPos(int z); - void SetAllWalls(const vector<Wall>& walls); - void SetWall(const Wall& wall, int index); - void SetAllTransitions(const vector<Transition>& transitions); - void SetTransition(const Transition& transition, int index); - void SetPolygon(const vector<CPoint>& poly); - - // Getter - Funktionen - int GetRoomID() const; - string GetCaption() const; - int GetZPos() const; - const vector<Wall>& GetAllWalls() const; - const Wall GetWall(int index) const; - const vector<Transition> GetAllTransitions() const; - const Transition GetTransition(int index) const; - const vector<CPoint>& GetPolygon() const; - - // Sonstiges - void AddWall(const Wall& w); - void DeleteWall(int index); - void AddTransition(const Transition& trans); - void DeleteTransition(int index); - void CloseTransition(int index); - void ConvertLineToPoly(); // Erstellt einen Polygonzug aus pLines - bool IsInRoom(const CPoint& ped) const; - bool IsStart() const; //später ändern im Moment wird Anfang und Ende in Caption festgelegt - bool IsExit() const; //später ändern im Moment wird Anfang und Ende in Caption festgelegt - CPoint GetCentre() const; - - - // Ein-Ausgabe - void LoadWalls(ifstream* buildingfile, int* i); - void WriteToErrorLog() const; - -}; - -#endif /* _ROOM_H */ - diff --git a/src/geometry/jul/Transition.cpp b/src/geometry/jul/Transition.cpp deleted file mode 100644 index aa994b9ae61729adb717c9622e8726d6da323965..0000000000000000000000000000000000000000 --- a/src/geometry/jul/Transition.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * File: Transition.cpp - * Author: andrea - * - * Created on 30. September 2010, 10:12 - */ - -#include "Transition.h" - -/************************************************************ - Konstruktoren - ************************************************************/ - -Transition::Transition() { - pLine = Line(); - pIsOpen = true; - pTransitionID = -1; - pCaption = "no transition caption"; - pRoom1 = -1; - pRoom2 = -1; -} - -Transition::Transition(const Transition& orig) { - pLine = orig.GetLine(); - pIsOpen = orig.GetIsOpen(); - pTransitionID = orig.GetID(); - pCaption = orig.GetCaption(); - pRoom1 = orig.GetRoom1(); - pRoom2 = orig.GetRoom2(); -} - -Transition::~Transition() { -} - -/************************************************************* - Setter-Funktionen - ************************************************************/ -void Transition::SetLine(const Line& l) { - pLine = l; -} - -void Transition::Close() { - pIsOpen = false; -} - -void Transition::Open() { - pIsOpen = true; -} - -void Transition::SetID(int ID) { - pTransitionID = ID; -} - -void Transition::SetCaption(string s) { - pCaption = s; -} - -void Transition::SetRoom1(int r1) { - pRoom1 = r1; -} - -void Transition::SetRoom2(int r2) { - pRoom2 = r2; -} - -/************************************************************* - Getter-Funktionen - ************************************************************/ -const Line& Transition::GetLine() const { - return pLine; -} - -bool Transition::GetIsOpen() const { - return pIsOpen; -} - -int Transition::GetID() const { - return pTransitionID; -} - -string Transition::GetCaption() const { - return pCaption; -} - -int Transition::GetRoom1() const { - return pRoom1; -} - -int Transition::GetRoom2() const { - return pRoom2; -} - -/************************************************************* - Sonstige Funktionen - ************************************************************/ - - -bool Transition::Connects(int r1id, int r2id) const { - bool c1 = (r1id == pRoom1) && (r2id == pRoom2); - bool c2 = (r1id == pRoom2) && (r2id == pRoom1); - return c1 | c2; -} - -int Transition::GetOtherRoom(int room_id) const { - if (room_id == pRoom1) return pRoom2; - else if (room_id == pRoom2) return pRoom1; - else { - printf("ERROR: \tNo exit found on the other side"); - exit(0); - } -} - -/************************************************************* - Ein-Ausgabe - ************************************************************/ - -void Transition::WriteToErrorLog() const { - char tmp[300]; - Line l = GetLine(); - sprintf(tmp, "\t\tTRANS: %d [%s] (%f, %f) -- (%f, %f)\n", GetID(), GetCaption().c_str(), l.GetPoint1().GetX() - , l.GetPoint1().GetY(), l.GetPoint2().GetX(), l.GetPoint2().GetY()); - printf("%s", tmp); -} diff --git a/src/geometry/jul/Transition.h b/src/geometry/jul/Transition.h deleted file mode 100644 index e123c622558780ecaed2b193da0685622d00bb33..0000000000000000000000000000000000000000 --- a/src/geometry/jul/Transition.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * File: Transition.h - * Author: andrea - * - * Created on 30. September 2010, 10:12 - */ - -#ifndef _TRANSITION_H -#define _TRANSITION_H - -#include <string> -using namespace std; - -#include "Line.h" - -class Transition { -private: - Line pLine; - bool pIsOpen; - int pTransitionID; - string pCaption; - int pRoom1; - int pRoom2; -public: - Transition(); - Transition(const Transition& orig); - virtual ~Transition(); - - // Setter -Funktionen - void SetLine(const Line& l); - void Close(); // schliesst Tür - void Open(); // öffnet Tür - void SetID(int ID); - void SetCaption(string s); - void SetRoom1(int r1); - void SetRoom2(int r2); - - // Getter - Funktionen - const Line& GetLine() const; - bool GetIsOpen() const; - int GetID() const; - string GetCaption() const; - int GetRoom1() const; - int GetRoom2() const; - - // Sonstiges - bool Connects(int r1id, int r2id) const; - int GetOtherRoom(int room_id) const; - - // Ein-Ausgabe - void WriteToErrorLog() const; -}; - -#endif /* _TRANSITION_H */ - diff --git a/src/geometry/jul/Wall.cpp b/src/geometry/jul/Wall.cpp deleted file mode 100644 index 7fc1a6aadbd05562d008bc242bc6965f2c5c3ac0..0000000000000000000000000000000000000000 --- a/src/geometry/jul/Wall.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * File: Wall.cpp - * Author: andrea - * - * Created on 30. September 2010, 11:47 - */ - -#include "Wall.h" - -/************************************************************ - Konstruktoren - ************************************************************/ - -Wall::Wall() { - pLine = Line(); -} - -Wall::Wall(const Wall& orig) { - pLine = orig.GetLine(); -} - -Wall::~Wall() { -} - -/************************************************************* - Setter-Funktionen - ************************************************************/ - -void Wall::SetLine(Line l) { - pLine = l; -} - -/************************************************************* - Getter-Funktionen - ************************************************************/ - -const Line& Wall::GetLine() const { - return pLine; -} - -/************************************************************* - Ausgabe - ************************************************************/ - -void Wall::WriteToErrorLog() const { - char tmp[300]; - Line l = GetLine(); - sprintf(tmp, "\t\tWALL: (%f, %f) -- (%f, %f)\n", l.GetPoint1().GetX() - , l.GetPoint1().GetY(), l.GetPoint2().GetX(), l.GetPoint2().GetY()); - printf("%s", tmp); -} diff --git a/src/geometry/jul/Wall.h b/src/geometry/jul/Wall.h deleted file mode 100644 index cbdcc2270417aa7df49d562acfb3219977655262..0000000000000000000000000000000000000000 --- a/src/geometry/jul/Wall.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * File: Wall.h - * Author: andrea - * - * Created on 30. September 2010, 11:47 - */ - -#ifndef _WALL_H -#define _WALL_H - -#include "Line.h" - -class Wall { -private: - Line pLine; -public: - Wall(); - Wall(const Wall& orig); - virtual ~Wall(); - - // Setter -Funktionen - void SetLine(Line l); - - // Getter - Funktionen - const Line& GetLine() const; - - //Ausgabe - void WriteToErrorLog() const; - -}; - -#endif /* _WALL_H */ - diff --git a/src/geometry/pg3/CBuilding.cpp b/src/geometry/pg3/CBuilding.cpp deleted file mode 100644 index 70170eef08106f2de4cde450bfac91d9878504d9..0000000000000000000000000000000000000000 --- a/src/geometry/pg3/CBuilding.cpp +++ /dev/null @@ -1,211 +0,0 @@ -#include "CBuilding.h" - - -CBuilding::CBuilding(CTextLog *errorlog) -// Constructor -{ -// pRoomCount = 0; // Anzahl der Raeume -// pTransitionCount = 0; // Anzahl der Uebergaenge (Transitions) - pCaption = "no caption"; // Name des Projekts -// pRooms = 0; -// pTransitions = 0; - pCellSize = 0.0; // Kantenlaenge der Zellen - pErrorLog = errorlog; -} -//--------------------------------------------------------------------------- - -CBuilding::~CBuilding(void) -// Destructor -{ -// if (pRooms != NULL) { -// delete [] pRooms; -// } - if (pRooms.size()>0) pRooms.clear(); - if (pTransitions.size()>0) pTransitions.clear(); -} -//--------------------------------------------------------------------------- - -void CBuilding::LoadFromFile(string filename) -// Laedt Geometrie-Datei mit dem Pfad "filename" ein -{ - char line[255]; - FILE *buildingfile = NULL; - //unused??? int value; - int fileversion; - int roomamount; - int transitionamount=0; - - // Zur Sicherheit die Daten zuruecksetzen: - /* - if (pRoomCount > 0) { - delete [] pRooms; - pRoomCount = 0; - } - if (pTransitionCount > 0) { - delete [] pTransitions; - pTransitionCount = 0; - } - */ - if (pRooms.size()>0) pRooms.clear(); - if (pTransitions.size()>0) pTransitions.clear(); - pCaption = "no caption"; - - // Datei oeffnen - buildingfile = fopen(filename.c_str(), "rt"); - if (buildingfile != NULL) { - while (fscanf(buildingfile,"%s",&line[0])!=EOF) { - // Header laden - if (!strcmp(line,"<header>")) { - fscanf(buildingfile,"%s",&line[0]); - while (strcmp(line,"</header>")) { - if (!strcmp(line,"caption")) { // Caption - char value[255]; - ReadLine(buildingfile, value); - string *tempstring = new string(value); - pCaption = *tempstring; - delete tempstring; - pCaption = DelFreeSpaces(pCaption); - } - else if (!strcmp(line,"cellsize")) // CellSize - fscanf(buildingfile,"%f", &pCellSize); - else if (!strcmp(line,"version")) // Version - fscanf(buildingfile,"%i", &fileversion); - else if (!strcmp(line,"rooms")) // Version - fscanf(buildingfile,"%i", &roomamount); - else - pErrorLog->AddEntry("ERROR: Unknown entry in <header> of project file."); - // naechsten Wert lesen - fscanf(buildingfile,"%s",&line[0]); - } - pErrorLog->AddEntry("INFO: Caption = "+pCaption); - char temp[255]; - sprintf(temp, "INFO: Cell size = %f m", pCellSize); - pErrorLog->AddEntry(temp); - if (fileversion != 1) pErrorLog->AddEntry("ERROR: File version != 1"); - } - // Ende: Header laden - - // Raeume laden - else if (!strcmp(line,"<rooms>")) { - fscanf(buildingfile,"%s",&line[0]); - // Anzahl der Raeume einlesen und Zeiger anlegen - if (!strcmp(line,"elements")) { - fscanf(buildingfile,"%i",&roomamount); - // pRooms = new CRoom [pRoomCount]; - pRooms.resize(roomamount); - fscanf(buildingfile,"%s",&line[0]); - } - while (strcmp(line,"</rooms>")) { - // Raum - if (!strcmp(line,"<room>")) { - int roomindex; - fscanf(buildingfile,"%s",&line[0]); // naechsten Wert lesen - if (!strcmp(line,"index")) { - fscanf(buildingfile,"%i", &roomindex); - printf("Loading room: %i/%i\n", roomindex, roomamount); - pRooms[roomindex].Initialize(pErrorLog, roomindex); - pRooms[roomindex].LoadFromFile(buildingfile); - } // Ende: Vom Index an Raumdaten einlesen - } // Ende: einen Raum laden - fscanf(buildingfile,"%s",&line[0]); // naechsten Wert lesen - } - } // Ende: alle Raeume laden - - // Transitions laden - else if (!strcmp(line,"<transitions>")) { - fscanf(buildingfile,"%s",&line[0]); - // Anzahl der Transitions einlesen und Zeiger anlegen - if (!strcmp(line,"elements")) { - fscanf(buildingfile,"%i",&transitionamount); - // pTransitions = new CTransition [pTransitionCount]; - pTransitions.resize(transitionamount); - fscanf(buildingfile,"%s",&line[0]); - } - while (strcmp(line,"</transitions>")) { - // Transition - if (!strcmp(line,"<transition>")) { - int transitionindex; - fscanf(buildingfile,"%s",&line[0]); // naechsten Wert lesen - if (!strcmp(line,"index")) { - fscanf(buildingfile,"%i", &transitionindex); - printf("Loading transition: %i/%i\n", transitionindex, transitionamount-1); - pTransitions[transitionindex].Initialize(pErrorLog, transitionindex); - pTransitions[transitionindex].LoadFromFile(buildingfile); - } // Ende: Vom Index an Transitiondaten einlesen - } // Ende: ein Transitiondaten laden - fscanf(buildingfile,"%s",&line[0]); // naechsten Wert lesen - } - } // Ende: alle Transitiondaten laden - } // Ende: bis an das Dateiende durch buildingfile lesen - // Transitions durchgehen und in verbundenen Raeumen und entsprechende Potenziale ausbreiten - // for (int count=0; count < transitionamount; ++count) { - // printf("Spreading transition potential: %i/%i\n", count, transitionamount-1); - // pRooms[pTransitions[count].GetRoom1()].SpreadPotential(count); - // pRooms[pTransitions[count].GetRoom2()].SpreadPotential(count); - // } - - // // Fehlerpruefungen - // // =============== - - // // Hat jede Transition ein Potenzial bekommen? (wenn nein, Pot-Wert == -2) - // int potvalue = -1; - // // Alle Raeume durchgehen - // for (int roomcount=0; roomcount<(int)pRooms.size(); ++roomcount) { - // printf("Checking for errors in room %i/%i\n", roomcount, pRooms.size()-1); - // // Alle Transitions durchgehen - // for (int transcount=0; transcount<pRooms[roomcount].GetTransitionCount(); ++transcount) { - // // Alle Zellen durchsuchen - // for (int x=0; x<pRooms[roomcount].GetXCellSize(); ++x) { - // for (int y=0; y<pRooms[roomcount].GetYCellSize(); ++y) { - // if (pRooms[roomcount].GetPotValue(pRooms[roomcount].GetTransitionTableValue(transcount), x, y)<-1) - // potvalue = -2; - // } - // } - // } - // } - // if (potvalue==-2) - // pErrorLog->AddEntry("ERROR: At least one potential is not spread correctly."); - - fclose(buildingfile); - } // Ende: buildingfile != NULL - else { - pErrorLog->AddEntry("ERROR: Cannot load building file: "+filename); - printf("Datei konnte nicht geöffnet werden!!!\n"); - } -} -//--------------------------------------------------------------------------- - -CRoom CBuilding::GetRoom(int index) -// Gibt Raum der Nummer "index" zurueck -{ -// if ((index>=0) && (index<pRoomCount)) - if ((index>=0) && (index<(int)pRooms.size())) - return pRooms[index]; - else { - pErrorLog->AddEntry("ERROR: Wrong 'index' in CBuiling::GetRoom()"); - printf("ERROR: Wrong 'index' in CBuiling::GetRoom()"); - exit(0); -// return ??? - } -} -//--------------------------------------------------------------------------- - -void CBuilding::SavePotData(string filename) -// zum Debuggen die Potenzialdaten der Raeume in "filename" speichern -{ - FILE *potfile; - - potfile = fopen(filename.c_str(), "wt"); -// for (int roomcount=0; roomcount<pRoomCount; ++roomcount) { - for (int roomcount=0; roomcount<(int)pRooms.size(); ++roomcount) { - fprintf(potfile, "Room Nr. %i, %s\n", roomcount, pRooms[roomcount].GetCaption().c_str()); - pRooms[roomcount].SavePotsToFile(potfile); - } -} - -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- - - - diff --git a/src/geometry/pg3/CBuilding.h b/src/geometry/pg3/CBuilding.h deleted file mode 100644 index d80ec2dbd12d7daec3617f57344d0fd8097dcc4e..0000000000000000000000000000000000000000 --- a/src/geometry/pg3/CBuilding.h +++ /dev/null @@ -1,52 +0,0 @@ -/*--------------------------------------------------------------------------- -CGeometry: -========== -Autor: Tim Meyer-Koenig (TraffGo HT) -Beschreibung: Verwaltet die gesamte Geometrie - ----------------------------------------------------------------------------*/ - -//--------------------------------------------------------------------------- -#ifndef CBuildingH -#define CBuildingH - -// Systemheader: -#include <string> -using namespace std; - -// Eigene Header: -#include "CRoom.h" -#include "CTransition.h" -#include "CTextLog.h" - -//--------------------------------------------------------------------------- - -class CBuilding { -private: -// Variablen - float pCellSize; // Kantenlaenge der Zellen -// int pRoomCount; // Anzahl der Raeume -// int pTransitionCount; // Anzahl der uebergaenge (Transitions) - string pCaption; // Name des Projekts - vector<CRoom> pRooms; // Liste der Räume - vector<CTransition> pTransitions; // Liste der Transitions - CTextLog *pErrorLog; // Fehlerlog, in das man Fehlermeldungen schreiben kann -// Funktionen - -public: - CBuilding(CTextLog *errorlog); // Constructor - ~CBuilding(void); // Destructor - void LoadFromFile(string filename); // Laedt Geometrie-Datei - void SavePotData(string filename); // zum Debuggen die Potenzialdaten der Raeume in "filename" speichern - -// Get-Funktionen: - CRoom GetRoom(int index); // Gibt Raum der Nummer "index" zurueck -// int GetRoomCount(void) {return pRoomCount;}; - int GetRoomCount(void) {return pRooms.size();}; -// int GetTransitionCount(void) {return pTransitionCount;}; - int GetTransitionCount(void) {return pTransitions.size();}; - string GetCaption(void) {return pCaption;}; -// Set-Funktionen: -}; - -#endif diff --git a/src/geometry/pg3/CCell.cpp b/src/geometry/pg3/CCell.cpp deleted file mode 100644 index c1548da126747d117ebde47246240384ad69f651..0000000000000000000000000000000000000000 --- a/src/geometry/pg3/CCell.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include "CCell.h" - -CCell::CCell(void) -// Constructor -{ -// Werte setzen - pIsOpen = true; // default: Zellen zugaenglich - pType = tFloor; // default: Floor - pAgentID = -1; // leer -// pPotValue = NULL; // Anzahl der Potenziale, wird spaeter angelegt - pTransitionID = -1; // default: -1 = kein uebergang -} -//--------------------------------------------------------------------------- - -CCell::~CCell(void) -// Destructor -{ -// if (pPotValue != NULL) -// delete [] pPotValue; - if (pPotValue.size()>0) - pPotValue.clear(); -} -//--------------------------------------------------------------------------- - -void CCell::Initialize(CTextLog *errorlog) -// Initialisieren der Klasse -{ - pErrorLog = errorlog; -} -//--------------------------------------------------------------------------- - -int CCell::GetPotValue(int index) -// Gibt Potenzialwert des Potenzials "index" zurueck -// bei Fehlern wird -1 zurueckgegeben -{ - if (index>=0) { // Plausibilitaetspruefung - if (pType==tWall) - return -1; - else - return pPotValue[index]; - } - else { - pErrorLog->AddEntry("ERROR: Index error in CCell::GetPotValue()."); - return -1; - } -} -//--------------------------------------------------------------------------- - -void CCell::SetPotValue(int index, int value) -// Setzt den Potenzialwert "value" fuer Potenzial "index" -{ - if (index>=0) { // Plausibilitaetspruefung - pPotValue[index] = value; // uebergebenen Wert uebernehmen - } - else - pErrorLog->AddEntry("ERROR: Index error in CCell::SetPotValue()."); -} -//--------------------------------------------------------------------------- - -void CCell::CopyData(CCell cell, int potvectorsize) -// kopiert Daten aus einem Zell-Element in sich selbst -{ - int i; -// unused??? int vectorsize; - - pIsOpen = cell.GetIsOpen(); - pType = cell.GetType(); - pAgentID = cell.GetAgentID(); - pTransitionID = cell.GetTransitionID(); -// Potenzial-Zeiger anlegen und Daten uebernehmen - if (pPotValue.size() > 0) pPotValue.clear(); -// pPotValue = new int [potvectorsize]; - pPotValue.resize(potvectorsize); - for (i=0; i<potvectorsize; ++i) // Daten uebergeben - pPotValue[i] = cell.GetPotValue(i); -} -//--------------------------------------------------------------------------- - -void CCell::IniPotSize(int size) -// legt *pPotValue entsprechend "size" an und faellt sie mit dem Defaultwert "-1" -{ -// auch wieder zum Debuggen aufgeblaeht - if (size>=0) { - pPotValue.resize(size); -// pPotValue = new int [size]; - for (int count=0; count<size; ++count) - pPotValue[count] = -2; - } - else - pErrorLog->AddEntry("ERROR: wrong 'size' in CCell::IniPotSize()"); -} -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- diff --git a/src/geometry/pg3/CCell.h b/src/geometry/pg3/CCell.h deleted file mode 100644 index 19c4dc50f258bc0e6104ade6b7dceb492336fcfa..0000000000000000000000000000000000000000 --- a/src/geometry/pg3/CCell.h +++ /dev/null @@ -1,52 +0,0 @@ -/*--------------------------------------------------------------------------- -CCell: -====== -Autor: Tim Meyer-K�nig (TraffGo HT) -Beschreibung: Verwaltet die Daten einer Zelle - ----------------------------------------------------------------------------*/ - -//--------------------------------------------------------------------------- -#ifndef CCellH -#define CCellH - -// Systemheader: -#include <vector> -using namespace std; - -// Eigene Header: -#include "Common.h" -#include "CTextLog.h" -//--------------------------------------------------------------------------- - -class CCell { -private: - bool pIsOpen; // ist Zelle zug�nglich oder nicht? Genutzt bei Up, Down und Door-Zellen - char pType; // Eigenschaft - int pAgentID; // Nummer des Agenten, wenn leer = -1 - vector<int> pPotValue; // Potenzialwert der Zelle, Zeigerlaenge = Anzahl der Potenziale - int pTransitionID; // Nummer des �bergangs, ansonsten = -1 - CTextLog *pErrorLog; - -public: - CCell(void); // Constructor - ~CCell(void); // Destructor -// Get-Funktionen: - bool GetIsOpen(void) {return pIsOpen;}; - char GetType(void) {return pType;}; - int GetAgentID(void) {return pAgentID;}; - int GetPotValue(int index); // Gibt Potenzialwert des Potenzials "index" zur�ck - int GetTransitionID(void) {return pTransitionID;}; - void Initialize(CTextLog *errorlog); // Initialisieren der Klasse - void IniPotSize(int size); // legt *pPotValue entsprechend "size" an - -// Set-Funktionen: - void CopyData(CCell cell, int potvectorsize); // kopiert Daten aus einem Zell-Element in sich selbst - void SetIsOpen(bool isopen) {pIsOpen=isopen;}; - void SetType(char type) {pType=type;}; - void SetAgentID(int agentid) {pAgentID=agentid;}; - void SetPotValue(int index, int value); // Setzt den Potenzialwert "value" f�r Potenzial "index" - void SetTransitionID(int transitionid) {pTransitionID=transitionid;}; -}; - -#endif diff --git a/src/geometry/pg3/CCoordsList.cpp b/src/geometry/pg3/CCoordsList.cpp deleted file mode 100644 index 16e7117816ad135a39b80a15110ce61b41678fe8..0000000000000000000000000000000000000000 --- a/src/geometry/pg3/CCoordsList.cpp +++ /dev/null @@ -1,188 +0,0 @@ -#include "CCoordsList.h" - - -/* -CCoordsList::CCoordsList(int startsize, int increment) -// Constructor -// startsize = erste Anzahl an Elementen -// increment = Anzahl an Elementen um die die Liste vergroessert wird -{ - pIncrement = increment; - pElementCount = 0; - pCoordsArraySize = startsize; -// pCoordsList = (CoordsListTyp*) calloc(1, sizeof(CoordsListTyp)); -} -*/ -//--------------------------------------------------------------------------- - -CCoordsList::CCoordsList() -// Constructor ohne Parameter -{ -// pIncrement = 1; -// pElementCount = 0; -// pCoordsArraySize = 0; -// pCoordsList = NULL; -// pCoordsList = (CoordsListTyp*) calloc(1, sizeof(CoordsListTyp)); -} -//--------------------------------------------------------------------------- - -CCoordsList::~CCoordsList(void) -// Destructor -{ -// if (pCoordsList!=NULL) { -// free(pCoordsList); -// pCoordsList = NULL; -// } - if (pCoordsList.size()>0) { - pCoordsList.clear(); - } -} -//--------------------------------------------------------------------------- - -void CCoordsList::Clear() -// Loescht die gesamte Elementen-Liste -{ -// free(pCoordsList); -// pCoordsList = NULL; - pCoordsList.clear(); -// pElementCount = 0; -// pCoordsArraySize = 0; -// pCoordsList = (CoordsListTyp*) calloc(1, sizeof(CoordsListTyp)); -} - -//--------------------------------------------------------------------------- - -bool CCoordsList::AddAndCheckCoords(int x, int y) -// (x, y, z) einfuegen, wenn noch nicht enthalten -// Rueckgabe: "false" wenn nocht nicht, "true", wenn wohl schon enthalten. -{ - bool returnvalue = false; - - returnvalue = IsCoordsAdded(x, y); -// wenn (x, y, z) noch nicht enthalten - if (!returnvalue) - AddCoords(x, y); - return returnvalue; -} -//--------------------------------------------------------------------------- - -void CCoordsList::AddCoordsAt(int i, int x, int y) -// Fuegt Koordinaten (x, y, z) an Position i ein, wenn i>FElementCount, anhaengen -{ - if (i>=0) { -// if (i<pElementCount) { - if (i<(int)pCoordsList.size()) { - pCoordsList[i].x = x; - pCoordsList[i].y = y; - } - else // wenn i groesser als Anzahl der Elemente -> erweiter - AddCoords(x, y); - } -} -//--------------------------------------------------------------------------- - -bool CCoordsList::IsCoordsAdded(int x, int y) -// Pruefen, ob (x, y, z) schon enthalten ist, wenn ja, true zurueck -{ - bool returnvalue = false; - int i; - -// for (i=0; i<pElementCount; ++i) { - for (i=0; i<(int)pCoordsList.size(); ++i) { - if (x == pCoordsList[i].x) - if (y == pCoordsList[i].y) - returnvalue = true; - } - return returnvalue; -} - -//--------------------------------------------------------------------------- -void CCoordsList::GetCoords(int position, int &x, int &y) -// Koordinaten an "position" abfragen -// wenn "position" Bloedsinn, dann (-1, -1, -1) zurueckgeben -{ -// if ((position > -1) && (position < pElementCount)) { - if ((position > -1) && (position < (int)pCoordsList.size())) { - x = pCoordsList[position].x; - y = pCoordsList[position].y; - } - else { - x = -1; - y = -1; - } -} - -//--------------------------------------------------------------------------- -void CCoordsList::AddCoords(int x, int y) -// Einfuegen von Koordinaten (x, y, z) ohne Pruefung -{ -// ++pElementCount; -// einfuegen -// if (pElementCount > pCoordsArraySize) { -// pCoordsArraySize += pIncrement; -// pCoordsList = (CoordsListTyp*) realloc(pCoordsList, pCoordsArraySize*sizeof(CoordsListTyp)); -// } - CoordsListTyp coords; - coords.x = x; - coords.y = y; - pCoordsList.push_back(coords); -} - -//--------------------------------------------------------------------------- -void CCoordsList::SaveCoordsList(string filename) -// Liste in ASCII-Datei "filename" speichern (evtl. zum debuggen) -{ - FILE *file; - int i; - - file = fopen(filename.c_str(), "wt"); - fprintf(file, "Content of CCoordsList:\n"); - for (i=0; i<(int)pCoordsList.size(); ++i) { - fprintf(file, "%i, %i\n", pCoordsList[pCoordsList.size()-1].x, pCoordsList[pCoordsList.size()-1].y); - } - fclose(file); -} - -//--------------------------------------------------------------------------- -void CCoordsList::SaveCoordsList(FILE *file) -// Liste in ASCII-Datei "filename" speichern (evtl. zum debuggen) -{ - int i; - -// for (i=0; i<pElementCount; ++i) { - for (i=0; i<(int)pCoordsList.size(); ++i) { - fprintf(file, "%i, %i\n", pCoordsList[pCoordsList.size()-1].x, pCoordsList[pCoordsList.size()-1].y); - } -} - -//--------------------------------------------------------------------------- -void CCoordsList::DeleteCoords(int x, int y) -// Loescht das Element (x, y, z) -{ - int i=0; - bool isfound = false; - -// alle Elemente durchsuchen bis Koordinaten (x, y, z) gefunden sind oder alles durchsucht ist - do { - if ((pCoordsList[i].x == x) && (pCoordsList[i].y == y)) - isfound = true; - ++i; -// } while (!isfound && (i<pElementCount)); - } while (!isfound && (i<(int)pCoordsList.size())); - --i; -// Entsprechende Koordinaten loeschen, wenn sie vorhanden sind - if (isfound) - DeleteElement(i); -} - -//--------------------------------------------------------------------------- -void CCoordsList::DeleteElement(int i) -// Loescht die Koordinaten an Position i -{ -// Letzten Listeneintrag nehmen und auf Position i setzen, Groesse des -// Arrays um 1 reduzieren -// pCoordsList[i].x = pCoordsList[pElementCount-1].x; -// pCoordsList[i].y = pCoordsList[pElementCount-1].y; -// --pElementCount; - pCoordsList.erase(pCoordsList.begin()+i); -} diff --git a/src/geometry/pg3/CCoordsList.h b/src/geometry/pg3/CCoordsList.h deleted file mode 100644 index 6af9f3a76f977c6b6764eff063d729c0940efc30..0000000000000000000000000000000000000000 --- a/src/geometry/pg3/CCoordsList.h +++ /dev/null @@ -1,53 +0,0 @@ -/*--------------------------------------------------------------------------- -CCoordsList: -============ -Autor: Tim Meyer-Koenig (TraffGo HT) -Beschreibung: CCoordsList verwaltet eine Liste zweidimensionaler Koordinaten. ----------------------------------------------------------------------------*/ - - -#ifndef CCoordsListH -#define CCoordsListH - -// Systemheader: -#include <string> -#include <stdio.h> -#include <cstdlib> -#include <vector> -using namespace std; - -// Eigene Header: - -//--------------------------------------------------------------------------- - -class CCoordsList { -private: -// int pIncrement; // Anzahl von Eintraegen, um die die Liste vergroessert wird -// int pElementCount; // Anzahl der Elemente in der Liste -// int pCoordsArraySize; // Groesse des Arrays (wird ja immer um "FIncrement" erweitert) - struct CoordsListTyp { // Koordinaten - int x; // kann mal auf beliebig viele Elemente erweitert werden. - int y; - }; - vector<CoordsListTyp> pCoordsList; -public: - CCoordsList(int startsize, int increment); // Constructor 1 - CCoordsList(); // Constructor 2 - ~CCoordsList(void); // Destructor - bool AddAndCheckCoords(int x, int y); // Einfuegen, wenn noch nicht 'drin - bool IsCoordsAdded(int x, int y); // Prueft, ob (x, y, z) enthalten ist, wenn ja, true zurueck - void GetCoords(int position, int &x, int &y); // Gibt Koordinaten zurueck - void AddCoords(int x, int y); // Einfuegen von Koordinaten - void AddCoordsAt(int i, int x, int y); // ueberschreibt Koordinaten an Stelle "i" - void SaveCoordsList(string filename); // Speichert Liste in Datei "filename" - void SaveCoordsList(FILE *file); // // Speichert Liste in Datei "file" - void DeleteCoords(int x, int y); // Loescht Koordinaten (x, y, z) - void DeleteElement(int i); // Loescht Element "i" - void Clear(); // Loescht gesamte Liste - -// int GetIncrement() {return pIncrement;}; // Wert um den Liste verlaengert wird -// int GetCoordsCount() {return pElementCount;}; // Anzahl Elemente - int GetCoordsCount() {return pCoordsList.size();}; // Anzahl Elemente -}; - -#endif diff --git a/src/geometry/pg3/CLine.cpp b/src/geometry/pg3/CLine.cpp deleted file mode 100644 index 8942ab041e58e7eb18868d658787d9983345c105..0000000000000000000000000000000000000000 --- a/src/geometry/pg3/CLine.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "CLine.h" - - - -CLine::CLine(void) -// Constructor -{ -// Werte setzen: - pIsOpen = false; // Default sind Linienelemente nicht zugänglich - pType = tWall; // Default: Wand - pPoint1.SetX(0.0); - pPoint1.SetY(0.0); // erster Punkt - pPoint2.SetX(0.0); - pPoint2.SetY(0.0); // zweiter Punkt - pTransitionID = -1; // Default: kein �bergang -} - -//--------------------------------------------------------------------------- - -CLine::~CLine(void) -// Destructor -{ -} -//--------------------------------------------------------------------------- - -void CLine::Initialize(CTextLog *errorlog) -// Initialisieren -{ - pErrorLog = errorlog; -} - -//--------------------------------------------------------------------------- - -void CLine::CopyData(CLine line) -// kopiert Daten aus einem Linien-Element in sich selbst -{ -// Werte aus "line" kopieren: - pIsOpen = line.GetIsOpen(); - pType = line.GetType(); - pPoint1 = line.GetPoint1(); - pPoint2 = line.GetPoint2(); - pTransitionID = line.GetTransitionID(); -} -//--------------------------------------------------------------------------- diff --git a/src/geometry/pg3/CLine.h b/src/geometry/pg3/CLine.h deleted file mode 100644 index e1597fecf3d4c70ab34620ea3ef82a1a6378ff4c..0000000000000000000000000000000000000000 --- a/src/geometry/pg3/CLine.h +++ /dev/null @@ -1,52 +0,0 @@ -/*--------------------------------------------------------------------------- -CLine: -====== -Autor: Tim Meyer-K�nig (TraffGo HT) -Beschreibung: Verwaltet Linienelemente, die durch ihre Eigenschaft und die -Koordinaten des Start- und Endpunkts definiert werden - ----------------------------------------------------------------------------*/ - -#ifndef CLineH -#define CLineH -// Systemheader: - -// Eigene Header: -#include "Common.h" -#include "CTextLog.h" -#include "../jul/CPoint.h" - -//--------------------------------------------------------------------------- - -class CLine { -private: - bool pIsOpen; // Ist Zelle zugänglich oder nicht - char pType; // Eigenschaft - CPoint pPoint1; // (Koordinaten des ersten Punkts) - CPoint pPoint2; // (Koordinaten des zweiten Punkts) - int pTransitionID; // Nummer des Übergangs, ansonsten "-1" - CTextLog *pErrorLog; - -public: - CLine(void); // Constructor - ~CLine(void); // Destructor - void Initialize(CTextLog *errorlog); // Initialisieren - -// Get-Funktionen: - bool GetIsOpen(void) {return pIsOpen;}; // ist Element zugänglich? - char GetType(void) {return pType;}; // gibt den Linientyp zurück - int GetTransitionID(void) {return pTransitionID;}; // gibt den Transition-Index zurück - const CPoint& GetPoint1(void) const {return pPoint1;}; // gibt die Koordinaten des Anfangspunkts zurück - const CPoint& GetPoint2(void) const {return pPoint2;}; // gibt die Koordinaten des Endpunkts zurück - -// Set-Funktionen: - void CopyData(CLine line); // kopiert Daten aus einem Linien-Element in sich selbst - void SetIsOpen(bool isopen) {pIsOpen=isopen;}; // ist Element zugänglich? - void SetType(char type) {pType=type;}; // setzt den Typ - void SetPoint1(const CPoint& p) {pPoint1=p;}; // setzt die Anfangskoordinaten - void SetPoint2(const CPoint& p) {pPoint2=p;}; // setzt die Endkoordinaten - void SetTransitionID(int &transitionid) {pTransitionID=transitionid;}; // setzt den Transition-Index -}; - - -#endif diff --git a/src/geometry/pg3/CRoom.cpp b/src/geometry/pg3/CRoom.cpp deleted file mode 100644 index 999ccb0d9ccfecbd8acfc9157edd052b96aa94b2..0000000000000000000000000000000000000000 --- a/src/geometry/pg3/CRoom.cpp +++ /dev/null @@ -1,518 +0,0 @@ -#include "CRoom.h" - - -CRoom::CRoom(void) -// Constructor -{ -// Allgemeine Daten: - pErrorLog = 0; - pRoomIndex = -1; // Raumindex - pCaption = "no caption"; // Raumname -// Geometriedaten: - pXCellPos = 0; - pYCellPos = 0; // Raumposition in Zellen - pZPos = 0; // Hoehenindex - pXCellSize = 0; - pYCellSize = 0; // Raumabmessung in Zellen -// pLineElementCount = 0; // Anzahl der Linienelemente - pTransitionCount = 0; // Anzahl der Transitions -// pTransitionTable = NULL; - pContPos = CPoint(); /* Default Konstruktor setzt automatisch (0,0) */ - pXContSize = 0.0; - pYContSize = 0.0; // Raumabmessung kontinuierlich in Metern -// pCells = 0; // zellulare Repraesentation des Raums [pXCellSize*pYCellSize] -// pLines = 0; // kontinuierliche Repraesentation des Raumes [pContElementCount] - -} -//--------------------------------------------------------------------------- - -CRoom::~CRoom(void) -// Destructor -{ -// if (pCells != NULL) -// delete [] pCells; - if (pCells.size()>0) pCells.clear(); -// if (pLines != NULL) -// delete [] pLines; - if (pLines.size()>0) pLines.clear(); -// if (pTransitionTable != NULL) -// free(pTransitionTable); - if (pTransitionTable.size()>0) pTransitionTable.clear(); -} -//--------------------------------------------------------------------------- - -void CRoom::Initialize(CTextLog *errorlog, int roomindex) -// weist pErrorLog zu -{ - pErrorLog = errorlog; - pRoomIndex = roomindex; -} -//--------------------------------------------------------------------------- - -bool CRoom::GetCell(int x, int y, CCell &cell) -// setzt Zeiger "cell" auf die Zelle an Position (x, y, z) -{ - bool returnvalue = false; - - if ((x>-1)&&(y>-1)) { // Pruefen ob Koordinaten innerhalb der Haupabmessung liegen - if ((x<pXCellSize)&&(y<pYCellSize)) { -// if (pCells != NULL) { - if (pCells.size()>0) { - cell = pCells[y*pXCellSize+x]; - returnvalue = true; - } - else { - pErrorLog->AddEntry("ERROR: in CRoom:GetCell(), pCells nicht angelegt"); - } - } - else { - pErrorLog->AddEntry("ERROR: in CRoom:GetCell(), x oder y > Maximalabmessungen"); - } - } - else { - pErrorLog->AddEntry("ERROR: in CRoom:GetCell(), x oder y < 0"); - } - return returnvalue; -} -//--------------------------------------------------------------------------- - -bool CRoom::GetLine(int index, CLine &line) -// setzt Zeiger "line" auf das Linienelement "index" -{ - bool returnvalue = false; - - if (index>-1) { // Pruefen ob Index innerhalb der Zeigerlaenge liegt -// if (index<pLineElementCount) { - if (index<(int)pLines.size()) { - line = pLines[index]; - returnvalue = true; - } - else { - pErrorLog->AddEntry("ERROR: in CRoom:GetLine(), index > Zeigerlaenge"); - } - } - else { - pErrorLog->AddEntry("ERROR: in CRoom:GetLine(), index < 0"); - } - return returnvalue; -} -//--------------------------------------------------------------------------- - -void CRoom::EditDoor(int index, bool isopen) -// oeffnet Tuer "index" -{ - int i; - -// Zellen durchgehen: -// if (pCells != 0) { - if (pCells.size() > 0) { - for (i=0; i<(pXCellSize*pYCellSize); ++i) { // alle Zellen durchgehen - if (pCells[i].GetTransitionID() == index) - pCells[i].SetIsOpen(isopen); - } - } - else - pErrorLog->AddEntry("ERROR: CRoom:OpenDoor(): pCells == 0"); - -// Linienelemente durchgehen: -// if (pLines != 0) { - if (pLines.size() > 0) { -// for (i=0; i<pLineElementCount; ++i) { // alle Zellen durchgehen - for (i=0; i<(int)pLines.size(); ++i) { // alle Zellen durchgehen - if (pLines[i].GetTransitionID() == index) - pLines[i].SetIsOpen(isopen); - } - } - else - pErrorLog->AddEntry("ERROR: CRoom:OpenDoor(): pLines == 0"); -} -//--------------------------------------------------------------------------- - -void CRoom::CopyData(CRoom room) -// Kopiert die Daten von "room" in sich selbst -{ - int i, x, y; - int lineelementcount = room.GetLineElementCount(); - - pRoomIndex = room.GetRoomIndex(); - pCaption = room.GetCaption(); - pXCellPos = room.GetXCellPos(); - pYCellPos = room.GetYCellPos(); - pZPos = room.GetZPos(); - pXCellSize = room.GetXCellSize(); - pYCellSize = room.GetYCellSize(); - - pTransitionCount = room.GetTransitionCount(); -// if (pTransitionTable!=NULL) free(pTransitionTable); - if (pTransitionTable.size()>0) pTransitionTable.clear(); -// pTransitionTable = (int*) calloc(pTransitionCount, sizeof(int)); - pTransitionTable.resize(pTransitionCount); - for (i=0; i<pTransitionCount; ++i) - pTransitionTable[i] = room.GetTransitionTableValue(i); - pContPos = room.GetContPos(); - pXContSize = room.GetXContSize(); - pYContSize = room.GetYContSize(); -// if (pCells!=NULL) delete [] pCells; - if (pCells.size()>0) pCells.clear(); -// pCells = new CCell [pXCellSize*pYCellSize]; - pCells.resize(pXCellSize*pYCellSize); - for (y=0; y<pYCellSize; ++y) - for (x=0; x<pXCellSize; ++x) { - CCell cell; - pCells[y*pXCellSize+x].Initialize(pErrorLog); - if (room.GetCell(x, y, cell)) - pCells[y*pXCellSize+x].CopyData(cell, pTransitionCount); - } -// if (pLines!=NULL) delete [] pLines; - if (pLines.size()>0) pLines.clear(); -// pLines = new CLine [pLineElementCount]; - pLines.resize(lineelementcount); - for (i=0; i<(int)pLines.size(); ++i) { - CLine line; - pLines[i].Initialize(pErrorLog); - if (room.GetLine(i, line)) - pLines[i].CopyData(line); - } -} -//--------------------------------------------------------------------------- - -void CRoom::LoadFromFile(FILE *buildingfile) -// Laedt Raumdaten aus Datei "buildingfile" -{ - char line[255]; - - fscanf(buildingfile,"%s",&line[0]); - while (strcmp(line,"</room>")) { - if (!strcmp(line,"caption")) { // Raumname - char value[255]; - ReadLine(buildingfile, value); - string *tempstring = new string(value); - pCaption = *tempstring; - delete tempstring; - pCaption = DelFreeSpaces(pCaption); - } - else if (!strcmp(line,"zpos")) // z-Position - fscanf(buildingfile,"%i", &pZPos); -// Zelldaten einlesen - else if (!strcmp(line,"<celldata>")) { - while (strcmp(line,"</celldata>")) { - fscanf(buildingfile,"%s",&line[0]); - if (!strcmp(line,"xpos")) // x-Position - fscanf(buildingfile,"%i", &pXCellPos); - else if (!strcmp(line,"ypos")) // y-Position - fscanf(buildingfile,"%i", &pYCellPos); - else if (!strcmp(line,"xmax")) // Abmessung in x-Richtung - fscanf(buildingfile,"%i", &pXCellSize); - else if (!strcmp(line,"ymax")) // Abmessung in y-Richtung - fscanf(buildingfile,"%i", &pYCellSize); - else if (!strcmp(line,"<cells>")) { // Zellen-Zeiger anlegen und Zellinfos einlesen - int x, y; - char cellvalue[2]; -// if (pCells != NULL) delete [] pCells; - if (pCells.size()>0) pCells.clear(); -// pCells = new CCell [pXCellSize*pYCellSize]; - pCells.resize(pXCellSize*pYCellSize); -// Zellen lesen - for (y=0; y<pYCellSize; ++y) { - for (x=0; x<pXCellSize; ++x) { - fscanf(buildingfile,"%1s", cellvalue); - if (!strcmp(cellvalue, "0")) // begehbarer Boden - pCells[y*pXCellSize+x].SetType(tFloor); - else if (!strcmp(cellvalue, "1")) // Wand - pCells[y*pXCellSize+x].SetType(tWall); - else if (!strcmp(cellvalue, "2")) // Stufe - pCells[y*pXCellSize+x].SetType(tStep); - else if (!strcmp(cellvalue, "x")) // Stufe - pCells[y*pXCellSize+x].SetType(tOutside); -// Bei Transition die Zahl zwischen den "T" einlesen und speichern - else if (!strcmp(cellvalue, "T")) { - string transition; - int count = 0; - transition.clear(); - fscanf(buildingfile,"%1s", cellvalue); - while (strcmp(cellvalue, "T")) { - transition += cellvalue[0]; - ++count; - fscanf(buildingfile,"%1s", cellvalue); - } - count = atoi(transition.c_str()); - pCells[y*pXCellSize+x].SetType(tTransition); - pCells[y*pXCellSize+x].SetTransitionID(atoi(transition.c_str())); - } - else - pErrorLog->AddEntry("ERROR: Unknown entry in <celldata> of project file."); - } - } - } - } - } // Ende: Zelldaten einlesen -// Kontinuierliche Daten einlesen: - else if (!strcmp(line,"<contdata>")) { - float xcontpos = 0.0; - float ycontpos = 0.0; - while (strcmp(line,"</contdata>")) { - fscanf(buildingfile,"%s",&line[0]); - if (!strcmp(line,"xpos")) // x-Position - fscanf(buildingfile,"%f", &xcontpos); - else if (!strcmp(line,"ypos")) // y-Position - fscanf(buildingfile,"%f", &ycontpos); - else if (!strcmp(line,"elements")) {// Elementanzahl - int lineelementcount; - fscanf(buildingfile,"%i", &lineelementcount); -// pLines = new CLine [pLineElementCount]; - pLines.resize(lineelementcount); - } - else if (!strcmp(line,"<elements>")) { // Zellen-Zeiger anlegen und Zellinfos einlesen - char type; - float x1, x2, y1, y2; - int transition = -1; -//unused??? int count; - int elementcount = 0; - while (strcmp(line,"</elements>")) { - fscanf(buildingfile,"%s",&line[0]); - if (!strcmp(line,"wall")) { // Wand-Element - fscanf(buildingfile, "%f %f %f %f", &x1, &y1, &x2, &y2); - type = tWall; - } - else if (!strcmp(line,"step")) { // Stufen-Element - fscanf(buildingfile, "%f %f %f %f", &x1, &y1, &x2, &y2); - type = tStep; - } - else if (!strcmp(line,"trans")) { // Transition-Element - fscanf(buildingfile, "%i %f %f %f %f", &transition, &x1, &y1, &x2, &y2); - type = tTransition; - } -// Linienelement der Liste hinzufuegen -// if-Abfrage um bei letztem durchlauf Speicherzugriffsfehler zu vermeiden -// if (elementcount<pLineElementCount) { - if (elementcount<(int)pLines.size()) { - pLines[elementcount].Initialize(pErrorLog); - pLines[elementcount].SetType(type); - CPoint point1(x1,y1); - pLines[elementcount].SetPoint1(point1); - CPoint point2(x2,y2); - pLines[elementcount].SetPoint2(point2); - if (transition>=0) - pLines[elementcount].SetTransitionID(transition); - } - ++elementcount; - } - } // Ende: <elements> - } - SetContPos(CPoint(xcontpos, ycontpos)); - } // Ende: Kontinuierliche Daten einlesen - fscanf(buildingfile,"%s",&line[0]); - } // Ende: <room> - -// Raum initialisieren -// Alle Zellen durchgehen und Anzahl der Transitions zaehlen, um danach alle Zellen -// zu initialisieren (Zeiger fuer Potenzial anlegen) - pTransitionCount = 0; -// if (pTransitionTable != NULL) free(pTransitionTable); - if (pTransitionTable.size()>0) pTransitionTable.clear(); -// pTransitionTable = (int*) calloc(1, sizeof(int)); - for (int count=0; count<pXCellSize*pYCellSize; ++count) { // alle Zellen durchsuchen - if (pCells[count].GetType() == tTransition) { // wenn Transition-Zelle - bool isfound = false; - for (int trans=0; trans<pTransitionCount; ++trans) { // gucken, ob diese Transition schon detektiert wurde - if (pTransitionTable[trans] == pCells[count].GetTransitionID()) - isfound = true; - } - if (!isfound) { // wenn Transition-Index noch nicht gefunden wurde, merken - ++pTransitionCount; - pTransitionTable.push_back(pCells[count].GetTransitionID()); -// pTransitionTable = (int*) realloc(pTransitionTable, pTransitionCount*sizeof(int)); -// pTransitionTable[pTransitionCount-1] = pCells[count].GetTransitionID(); - } - } - } - for (int count=0; count<pXCellSize*pYCellSize; ++count) { // alle Zellen initialisieren - pCells[count].IniPotSize(pTransitionCount); - } -} // Ende: LoadFromFile() -//--------------------------------------------------------------------------- - -CLine CRoom::GetLine(int index) -// gibt Linienelement "index" zurueck -{ -// if ((index>=0) && (index<pLineElementCount)) - if ((index>=0) && (index<(int)pLines.size())) - return pLines[index]; - else { - pErrorLog->AddEntry("ERROR: Wrong 'index' in CRoom::GetLine()"); - printf("ERROR: Wrong 'index' in CRoom::GetLine()\n"); - exit(0); - } -} -//--------------------------------------------------------------------------- - -void CRoom::SpreadPotential(int transition) -// breitet das Potenzial von "transition" im Raum aus -{ - int i, j; - int x, y; - int potvalue = 0; - int transitionindex = -1; -// CCoordsList *oldcells = new CCoordsList(0, 50); // weiterfuehrende Zellen anlegen - CCoordsList *oldcells = new CCoordsList; // weiterfuehrende Zellen anlegen - CCoordsList *newcells; - -// "transitionindex" bestimmen, d.h. den Index des Zellenarrays, in dem die Potenzialwerte -// der globalen Transition mit der Nummer "transition" gespeichert werden - for (i=0; i<pTransitionCount; ++i) { - if (pTransitionTable[i] == transition) - transitionindex = i; - } - -// alle Zellen nach Transition-Zellen von "transition" durchsuchen, in "contcells" -// merken und ihren Potenzialwert auf 0 setzen - for (y=0; y<pYCellSize; ++y) { - for (x=0; x<pXCellSize; ++x) { - if (pCells[y*pXCellSize+x].GetTransitionID() == transition) { - oldcells->AddAndCheckCoords(x, y); - pCells[y*pXCellSize+x].SetPotValue(transitionindex, potvalue); - } - } - } -// Potenzial von "contcells" aus ausbreiten - do { - ++potvalue; -// newcells = new CCoordsList(0,50); - newcells = new CCoordsList; -// alle alten Zellen durchgehen und nur ueber die Kanten neue Nachbarn suchen - for (i=0; i<oldcells->GetCoordsCount(); ++i) { - for (j=1; j<9; j+=2) { - oldcells->GetCoords(i, x, y); -// "unentdeckte" Zelle gefunden, also in "newcells" merken und Potenzialwert setzen - if (LookPotValue(transition, j, x, y)==-2) { - newcells->AddAndCheckCoords(x, y); - pCells[y*pXCellSize+x].SetPotValue(transitionindex, potvalue); - } - } // Ende 'drumherum ueber Kanten gucken - } // Ende 'oldcells[]' durchgehen -// Neue Zellen zu alten Zellen umschaufeln - for (i=0; i<newcells->GetCoordsCount(); ++i) { - newcells->GetCoords(i, x, y); - oldcells->AddCoords(x, y); - } - newcells->Clear(); - ++potvalue; -// alle alten Zellen durchgehen und ueber die Kanten & Ecken (2. Schritt) neue Nachbarn suchen - for (i=0; i<oldcells->GetCoordsCount(); ++i) { - for (j=1; j<9; j+=1) { - oldcells->GetCoords(i, x, y); -// Unentdeckte normale Zelle gefunden - if (LookPotValue(transition, j, x, y)==-2) { - newcells->AddCoords(x, y); - pCells[y*pXCellSize+x].SetPotValue(transitionindex, potvalue); - } // Ende "unentdeckte Zelle" gefunden - } // Ende 'drumherum ueber Ecken & Kanten gucken - } // Ende 'oldcells[]' durchgehen -// Neue Zellen in alte Zellen und nach neuen Nachbarzellen suchen - delete oldcells; - oldcells = NULL; - oldcells = newcells; - newcells = NULL; - } while (oldcells->GetCoordsCount() != 0); - if (oldcells != NULL) { - delete oldcells; - oldcells = NULL; - } -} -//--------------------------------------------------------------------------- - -int CRoom::LookPotValue(int transition, int direction, int &x, int &y) -// Gibt den Wert des Potenzials 'transition' in Richtung 'direction' von (x,y) aus zurueck -// x, y werden dabei entsprechend geaendert -// Wenn vor Wand oder vor Rand des Rechenfelds, dann wird -1 zurueckgegeben -// Richtung: im Uhrzeigersinn hochgezaehlt, 1 = Zelle in Richtung "oben", also (0,-1) -{ - int transitionindex = -1; - -// "transitionindex" bestimmen - for (int i=0; i<pTransitionCount; ++i) { - if (pTransitionTable[i] == transition) - transitionindex = i; - } -// Rechenrand: - if ((x==0)&&((direction==6)||(direction==7)||(direction==8))) - return -1; - else if ((x==pXCellSize-1)&&((direction==2)||(direction==3)||(direction==4))) - return -1; - else if ((y==0)&&((direction==8)||(direction==1)||(direction==2))) - return -1; - else if ((y==pYCellSize-1)&&((direction==4)||(direction==5)||(direction==6))) - return -1; -// im Rechengebiet: - else { -// jetzige Zelle - switch (direction) { - case 1: --y; break; - case 2: ++x; --y; break; - case 3: ++x; break; - case 4: ++x; ++y; break; - case 5: ++y; break; - case 6: --x; ++y; break; - case 7: --x; break; - case 8: --x; --y; break; - default: pErrorLog->AddEntry("ERROR: Direction error in CRoom::GetPotValue()"); - } - return GetPotValue(transition, x, y); // pCells[y*pXCellSize+x].GetPotValue(transitionindex); - } -} -//--------------------------------------------------------------------------- - -int CRoom::GetPotValue(int transition, int x, int y) -// Gibt den Wert des Potenzials 'transition' auf (x,y) zurueck -// Wenn Wandzelle, wird -1 zurueckgegeben -{ - int transitionindex = -1; - -// "transitionindex" bestimmen - for (int i=0; i<pTransitionCount; ++i) { - if (pTransitionTable[i] == transition) - transitionindex = i; - } -// ausserhalb des Raumes - if ((x<0)||(x>pXCellSize)||(y<0)||(y>pYCellSize)) - return -1; -// im Rechengebiet: - else if ((pCells[y*pXCellSize+x].GetType()==tFloor) || (pCells[y*pXCellSize+x].GetType()==tStep) || (pCells[y*pXCellSize+x].GetType()==tTransition)) { - return pCells[y*pXCellSize+x].GetPotValue(transitionindex); - } - else - return -1; -} -//--------------------------------------------------------------------------- - -int CRoom::GetTransitionTableValue(int index) -// gibt Wert von Position "index" zurueck -{ - if ((index>=0) && (index<pTransitionCount)) - return pTransitionTable[index]; - else { - pErrorLog->AddEntry("ERROR: Wrong Index in CRoom::GetTransitionTableValue()"); - return -1; - } -} -//--------------------------------------------------------------------------- - -void CRoom::SavePotsToFile(FILE *potfile) -// Speichert Potenziale int "potfile", zum Debuggen -{ - int x, y; - for (int transcount=0; transcount<pTransitionCount; ++transcount) { - fprintf(potfile, "Transition %i:\n", pTransitionTable[transcount]); - for (y=0; y<pYCellSize; ++y) { - for (x=0; x<pXCellSize; ++x) { - fprintf(potfile, "%4i,", pCells[y*pXCellSize+x].GetPotValue(transcount)); - } - fprintf(potfile, "\n"); - } - fprintf(potfile, "\n"); - } - fprintf(potfile, "\n"); -} -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- diff --git a/src/geometry/pg3/CRoom.h b/src/geometry/pg3/CRoom.h deleted file mode 100644 index 1c66c6fb69fb1486a0fab831f48b9fb85eb6a8c7..0000000000000000000000000000000000000000 --- a/src/geometry/pg3/CRoom.h +++ /dev/null @@ -1,105 +0,0 @@ -/*--------------------------------------------------------------------------- -CRoom: -====== -Autor: Tim Meyer-Koenig (TraffGo HT) -Beschreibung: Verwaltet die Daten eines Raums, der sowohl kontinuierlich (*CLine) -und zellular (*CCell) repraesentiert wird. - ----------------------------------------------------------------------------*/ - -//--------------------------------------------------------------------------- -#ifndef CRoomH -#define CRoomH - -// Systemheader: -#include <string> -#include <cstring> -#include <cstdlib> -#include <stdio.h> -using namespace std; - -// Eigene Header: -#include "Common.h" -#include "CTextLog.h" -#include "CCell.h" -#include "CLine.h" -#include "CCoordsList.h" - -//--------------------------------------------------------------------------- - -class CRoom { -private: - int pRoomIndex; // Raumindex - string pCaption; // Raumname - CTextLog *pErrorLog; // Log-Klasse fuer Fehlermeldungen - -// Geometriedaten: - int pZPos; // Hoehenindex, in meinen Augen ist hier die Unterscheidung kontunuierlich/zellular egal - int pXCellPos; - int pYCellPos; // Raumposition in Zellen - int pXCellSize; - int pYCellSize; // Raumabmessung in Zellen -// int pLineElementCount; // Anzahl der Linienelemente - int pTransitionCount; // Anzahl der Transitions (=Anzahl der Potenziale) - vector<int> pTransitionTable; // uebersetzungstabelle pTransitionsTable[0..pTransitionCount-1]=globale Transition-Nummer - CPoint pContPos; // Raumposition kontinuierlich in Metern - float pXContSize; - float pYContSize; // Raumabmessung kontinuierlich in Metern - vector<CCell> pCells; // zellulare Repraesentation des Raums [pXCellSize*pYCellSize] - vector<CLine> pLines; // kontinuierliche Repraesentation des Raumes [pContElementCount] - -/* !Agentendaten habe ich erstmal generell auskommentiert! -// Agentendaten: - int pTransAgentCount; // Anzahl der Agenten auf Transition-Zellen - int *pTransAgents; // Indizes der Agenten auf Trans-Zellen [pTransAgentCount] - int pAgentCount; // Anzahl der Agenten in diesem Raum - CAgents *pAgents; // Agenten des Raumes [pAgentCount] -*/ -public: - CRoom(void); // Constructor - ~CRoom(void); // Destructor - void Initialize(CTextLog *errorlog, int roomindex); // weist pErrorLog zu - void EditDoor(int index, bool isopen); // setzt Oeffnungszustand der Tuer "index" auf "isopen" - void CopyData(CRoom room); // kopiert die Daten von "room" in sich selbst - void LoadFromFile(FILE *buildingfile); // laedt Raumdaten aus Datei "buildingfile" - void SpreadPotential(int transition); // breitet das Potenzial von "transition" im Raum aus - void SavePotsToFile(FILE *potfile); // Speichert Potenziale int "potfile", zum Debuggen -// Get-Funktionen: - bool GetCell(int x, int y, CCell &cell); // setzt Zeiger "cell" auf die Zelle an Position (x, y) - bool GetLine(int index, CLine &line); // setzt Zeiger "line" auf das Linienelement "index" - CLine GetLine(int index); // gibt Linienelement "index" zurueck - int GetRoomIndex(void) {return pRoomIndex;}; // Raumindex - string GetCaption(void) {return pCaption;}; // Raumname - int GetXCellPos(void) {return pXCellPos;}; - int GetYCellPos(void) {return pYCellPos;}; // Raumposition in Zellen - int GetZPos(void) {return pZPos;}; // Hoehenindex - int GetXCellSize(void) {return pXCellSize;}; - int GetYCellSize(void) {return pYCellSize;}; // Raumabmessung in Zellen -// int GetLineElementCount(void) {return pLineElementCount;}; // Anzahl der Linienelemente - int GetLineElementCount(void) {return pLines.size();}; // Anzahl der Linienelemente - int LookPotValue(int transition, int direction, int &x, int &y); // gibt den Wert des Potenzials 'transition' in Richtung 'direction' von (x,y) aus zurueck - int GetPotValue(int transition, int x, int y); // gibt den Wert des Potenzials 'transition' in Richtung 'direction' von (x,y) aus zurueck - int GetTransitionCount(void) {return pTransitionCount;}; // gibt Anzahl der Transitions zurueck - int GetTransitionTableValue(int index); // gibt Wert von Position "index" zurueck - const CPoint& GetContPos(void) const {return pContPos;}; // Raumposition kontinuierlich in Metern - float GetXContSize(void) {return pXContSize;}; - float GetYContSize(void) {return pYContSize;}; // Raumabmessung kontinuierlich in Metern - -// Set-Funktionen: -/* diese hier sind vielleicht gar nicht noetig: - void SetRoomIndex(int index) {pRoomIndex = index;}; // Raumindex - void SetCaption(string caption) {pCaption = caption;}; // Raumname - void SetXCellPos(int xpos) {pXCellPos = xpos;}; - void SetYCellPos(int ypos) {pYCellPos = ypos;}; - void SetZCellPos(int zpos) {pZCellPos = zpos;}; // Raumposition in Zellen - void SetXCellSize(int xsize) {pXCellSize = xsize;}; - void SetYCellSize(int ysize) {pYCellSize = ysize;}; // Raumabmessung in Zellen - void SetContElementCount(int count) {pContElementCount = count;}; // Anzahl der Linienelemente - void SetZContPos(float zpos) {pZContPos = zpos;}; // Raumposition kontinuierlich in Metern - void GetXContSize(float xsize) {pXContSize = xsize;}; - void GetYContSize(float ysize) {pYContSize = ysize;}; // Raumabmessung kontinuierlich in Metern -*/ - void SetContPos(const CPoint& p){pContPos=p;}; // setzt die Punktkoordinaten in pContPos -}; - -#endif diff --git a/src/geometry/pg3/CTextLog.cpp b/src/geometry/pg3/CTextLog.cpp deleted file mode 100644 index 0e0a65ca59cd7b61ea31f7b3854f026b256e9dca..0000000000000000000000000000000000000000 --- a/src/geometry/pg3/CTextLog.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "CTextLog.h" - - - -CTextLog::CTextLog(void) -// Constructor -{ -// pTextEntries = 0; -// pTextEntryCount = 0; -} -//--------------------------------------------------------------------------- - -CTextLog::~CTextLog(void) -// Destructor -{ - if (pTextEntries.size() > 0) pTextEntries.clear(); -} -//--------------------------------------------------------------------------- - -void CTextLog::AddEntry(string text) -// fuegt einen Eintrag hinzu -{ - pTextEntries.push_back(text); -/* - string *tempvector; - int i; - - tempvector = pTextEntries; // Temp-Vektor anlegen - ++pTextEntryCount; - pTextEntries = new string [pTextEntryCount]; - for (i=0; i<pTextEntryCount-1; ++i) // Daten aus Temp-Vektor in neuen Vektor kopieren - pTextEntries[i] = tempvector[i]; - delete [] tempvector; - pTextEntries[pTextEntryCount-1] = text; // Eintrag hinten anf�gen -*/ -} -//--------------------------------------------------------------------------- - -void CTextLog::SaveToFile(string path) -// speichert alle Eintr�ge in einer txt-Datei -{ - FILE *logfile; - int i; - - logfile = fopen(path.c_str(), "wt"); - - if(logfile != NULL){ - // Header: - fprintf(logfile, "Simulator Log-Datei\n"); - fprintf(logfile, "===================\n\n"); - // Inhalt - fprintf(logfile, "Meldungen:\n"); - fprintf(logfile, "----------\n"); - for (i=0; i<(int)pTextEntries.size(); ++i) - fprintf(logfile, "%i) %s\n\n",i, pTextEntries[i].c_str()); - fclose(logfile); - } - else{ - printf("Can not open file [%s]! (errorlogfile)\n", path.c_str()); - exit(EXIT_FAILURE); - } -} -//--------------------------------------------------------------------------- - - diff --git a/src/geometry/pg3/CTextLog.h b/src/geometry/pg3/CTextLog.h deleted file mode 100644 index f812d36f973754c4946a5c537471a8c1496fca42..0000000000000000000000000000000000000000 --- a/src/geometry/pg3/CTextLog.h +++ /dev/null @@ -1,37 +0,0 @@ -/*--------------------------------------------------------------------------- -CTextLog: -========= -Autor: Tim Meyer-K�nig (TraffGo HT) -Beschreibung: Textlog verwaltet Text-Eintr�ge und speichert sie bei Bedarf in eine -Datei. So k�nnen z.B. Fehler mitgelogged werden. - ----------------------------------------------------------------------------*/ - -//--------------------------------------------------------------------------- -#ifndef CTextLogH -#define CTextLogH - -// Systemheader: -#include <string> -#include <vector> -using namespace std; -#include <stdio.h> -#include <cstdlib> - -// Eigene Header: - -//--------------------------------------------------------------------------- - -class CTextLog { -private: - vector<string> pTextEntries; -// int pTextEntryCount; -public: - CTextLog(void); // Constructor - ~CTextLog(void); // Destructor - void AddEntry(string text); // f�gt einen Eintrag hinzu - void SaveToFile(string path); // speichert alle Eintr�ge in einer txt-Datei -}; - -#endif - \ No newline at end of file diff --git a/src/geometry/pg3/CTransition.cpp b/src/geometry/pg3/CTransition.cpp deleted file mode 100644 index c60a002b150f2cb0a4e2daab6a544f5aebb9bd7f..0000000000000000000000000000000000000000 --- a/src/geometry/pg3/CTransition.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "CTransition.h" - - -CTransition::CTransition(void) -// Constructor -{ - pTransitionIndex = -1; // �bergangsindex - pRoom1 = -1; - pRoom2 = -1; // Indizes der R�ume, die verbunden werden - pCaption = "no caption"; // Name, z.B. bei T�ren entsprechend des Raumbuchs -} -//--------------------------------------------------------------------------- - -CTransition::~CTransition(void) -// Destructor -{ -} -//--------------------------------------------------------------------------- - -void CTransition::Initialize(CTextLog *errorlog, int i) -// Initialisieren -{ - pErrorLog = errorlog; - pTransitionIndex = i; -} -//--------------------------------------------------------------------------- - -void CTransition::CopyData(CTransition transition) -// Kopiert die Daten von "transition" in sich selbst -{ - pTransitionIndex = transition.GetTransitionIndex(); - pRoom1 = transition.GetRoom1(); - pRoom2 = transition.GetRoom2(); - pCaption = transition.GetCaption(); -} -//--------------------------------------------------------------------------- - -void CTransition::LoadFromFile(FILE *buildingfile) -// L�dt Transitiondaten aus Datei "buildingfile" -{ - char line[255]; - - fscanf(buildingfile,"%s",&line[0]); - while (strcmp(line,"</transition>")) { - if (!strcmp(line,"caption")) { // Raumname - char value[255]; - ReadLine(buildingfile, value); - string *tempstring = new string(value); - pCaption = *tempstring; - delete tempstring; - pCaption = DelFreeSpaces(pCaption); - } - else if (!strcmp(line,"room1")) // Raum 1 (auf der einen Seite des Transitionpunkts) - fscanf(buildingfile,"%i", &pRoom1); - else if (!strcmp(line,"room2")) // Raum 2 (auf der anderen Seite des Transitionpunkts) - fscanf(buildingfile,"%i", &pRoom2); - fscanf(buildingfile,"%s",&line[0]); // n�chsten Eintrag einlesen - } // Ende: <transition> -} - -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- diff --git a/src/geometry/pg3/CTransition.h b/src/geometry/pg3/CTransition.h deleted file mode 100644 index 4a90455af2d26664a31a12df105d9fb3955660b5..0000000000000000000000000000000000000000 --- a/src/geometry/pg3/CTransition.h +++ /dev/null @@ -1,54 +0,0 @@ -/*--------------------------------------------------------------------------- -CTransition: -============ -Autor: Tim Meyer-Koenig (TraffGo HT) -Beschreibung: Verwaltet die Daten eines Uebergangs zwischen zwei Raeumen, also einer -Tuerschwelle, oder der ersten, bzw. letzten Stufe einer Treppe. Geometrisch werden -die Daten in CRoom verwaltet, doch CTransition enthaelt die Informationen darueber, -welche Raeume verbunden werden. - ----------------------------------------------------------------------------*/ - -//--------------------------------------------------------------------------- -#ifndef CTransitionH -#define CTransitionH - -// Systemheader: -#include <stdio.h> -#include <string> -using namespace std; - -// Eigene Header: -#include "CTextLog.h" -#include "Common.h" -//--------------------------------------------------------------------------- - -class CTransition { -private: - int pTransitionIndex; // Uebergangsindex - int pRoom1; - int pRoom2; // Indizes der Raeume, die verbunden werden - string pCaption; // Name, z.B. bei Tueren entsprechend des Raumbuchs - CTextLog *pErrorLog; - -public: - CTransition(void); // Constructor - ~CTransition(void); // Destructor - void Initialize(CTextLog *errorlog, int i); // Initialisieren - void CopyData(CTransition transition); // Kopiert die Daten von "transition" in sich selbst - void LoadFromFile(FILE *buildingfile); // Laedt Transitiondaten aus Datei "buildingfile" - -// Get-Funktionen: - int GetTransitionIndex(void) {return pTransitionIndex;}; // Uebergangsindex - int GetRoom1(void) {return pRoom1;}; - int GetRoom2(void) {return pRoom2;}; // Indizes der Raeume, die verbunden werden - string GetCaption(void) {return pCaption;}; // Name, z.B. bei Tueren entsprechend des Raumbuchs - -// Set-Funktionen: - void SetTransitionIndex(int index) {pTransitionIndex = index;}; // Uebergangsindex - void SetRoom1(int room1) {pRoom1 = room1;}; - void SetRoom2(int room2) {pRoom2 = room2;}; // Indizes der Raeume, die verbunden werden - void SetCaption(string caption) {pCaption = caption;}; // Name, z.B. bei Tueren entsprechend des Raumbuchs -}; - -#endif diff --git a/src/geometry/pg3/Common.cpp b/src/geometry/pg3/Common.cpp deleted file mode 100644 index 159679eba2f098ff6b6794bd48a8893bb3a7d83b..0000000000000000000000000000000000000000 --- a/src/geometry/pg3/Common.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "Common.h" - - -void ReadLine(FILE *file, char *line) -// Liest die gesamte Zeile aus "file" in "line" ein -{ - do { - if (fscanf (file,"%[^\r\n]\n",line) == EOF) - strcpy (line,"END"); - } while ((line[0]) == '#'); -} -//--------------------------------------------------------------------------- - -string DelFreeSpaces(string value) -// Entfernt Leerzeichen am Anfang von "value" -{ -// while (value.IsDelimiter(" ", 1)) { -// value.Delete(1, 1); -// } - while (value.compare(0, 1, " ")==0) - value.erase(0,1); - return value; -} -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- diff --git a/src/geometry/pg3/Common.h b/src/geometry/pg3/Common.h deleted file mode 100644 index 2b4ae1a1d76a739178b778935ab1f00b5ef4b462..0000000000000000000000000000000000000000 --- a/src/geometry/pg3/Common.h +++ /dev/null @@ -1,31 +0,0 @@ -/*--------------------------------------------------------------------------- -Common: -======= -Autor: Tim Meyer-K�nig (TraffGo HT) -Beschreibung: Enth�lt allgemeine Definitionen und Funktionen - ----------------------------------------------------------------------------*/ -#ifndef CommonH -#define CommonH -//--------------------------------------------------------------------------- - -#include <stdio.h> -#include <string> -#include <cstring> -using namespace std; - -//--------------------------------------------------------------------------- - -// Linien- und Zelltypen; -#define tFloor 0 -#define tWall 1 -#define tStep 2 -#define tTransition 3 -#define tOutside 4 -//--------------------------------------------------------------------------- - -void ReadLine(FILE *file, char *line); // Liest die gesamte Zeile aus "file" in "line" ein -string DelFreeSpaces(string value); // Entfernt Leerzeichen am Anfang von "value" - -#endif - \ No newline at end of file diff --git a/src/tinyxml/tinystr.cpp b/src/tinyxml/tinystr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..066576820516de3bae97b08f9258468f9cc136f4 --- /dev/null +++ b/src/tinyxml/tinystr.cpp @@ -0,0 +1,111 @@ +/* +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. + +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. + +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. +*/ + + +#ifndef TIXML_USE_STL + +#include "tinystr.h" + +// Error value for find primitive +const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1); + + +// Null rep. +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); + } +} + + +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; +} + + +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; +} + + +TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) +{ + 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 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; +} + + +#endif // TIXML_USE_STL diff --git a/src/tinyxml/tinystr.h b/src/tinyxml/tinystr.h new file mode 100644 index 0000000000000000000000000000000000000000..89cca3341564c0337e3e940bfa4ae053e84e656c --- /dev/null +++ b/src/tinyxml/tinystr.h @@ -0,0 +1,305 @@ +/* +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. + +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. + +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. +*/ + + +#ifndef TIXML_USE_STL + +#ifndef TIXML_STRING_INCLUDED +#define TIXML_STRING_INCLUDED + +#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: +*/ +#if defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // 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 +#else + #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. +*/ +class TiXmlString +{ + public : + // The size type used + typedef size_t size_type; + + // Error value for find primitive + static const size_type npos; // = -1; + + + // TiXmlString empty constructor + TiXmlString () : rep_(&nullrep_) + { + } + + // TiXmlString copy constructor + TiXmlString ( const TiXmlString & copy) : rep_(0) + { + init(copy.length()); + memcpy(start(), copy.data(), length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) + { + init( static_cast<size_type>( strlen(copy) )); + memcpy(start(), copy, length()); + } + + // TiXmlString constructor, based on a string + TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) + { + init(len); + memcpy(start(), str, len); + } + + // TiXmlString destructor + ~TiXmlString () + { + quit(); + } + + TiXmlString& operator = (const char * copy) + { + return assign( copy, (size_type)strlen(copy)); + } + + TiXmlString& operator = (const TiXmlString & copy) + { + return assign(copy.start(), copy.length()); + } + + + // += operator. Maps to append + TiXmlString& operator += (const char * suffix) + { + return append(suffix, static_cast<size_type>( strlen(suffix) )); + } + + // += operator. Maps to append + TiXmlString& operator += (char single) + { + return append(&single, 1); + } + + // += operator. Maps to append + TiXmlString& operator += (const TiXmlString & suffix) + { + return append(suffix.data(), suffix.length()); + } + + + // Convert a TiXmlString into a null-terminated char * + const char * c_str () const { return rep_->str; } + + // Convert a TiXmlString into a char * (need not be null terminated). + const char * data () const { return rep_->str; } + + // Return the length of a TiXmlString + size_type length () const { return rep_->size; } + + // Alias for length() + size_type size () const { return rep_->size; } + + // Checks if a TiXmlString is empty + bool empty () const { return rep_->size == 0; } + + // Return capacity of string + size_type capacity () const { return rep_->capacity; } + + + // single char extraction + const char& at (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // [] operator + char& operator [] (size_type index) const + { + assert( index < length() ); + return rep_->str[ index ]; + } + + // find a char in a string. Return TiXmlString::npos if not found + size_type find (char lookup) const + { + return find(lookup, 0); + } + + // find a char in a string from an offset. Return TiXmlString::npos if not found + size_type find (char tofind, size_type offset) const + { + if (offset >= length()) return npos; + + for (const char* p = c_str() + offset; *p != '\0'; ++p) + { + if (*p == tofind) return static_cast< size_type >( p - c_str() ); + } + return npos; + } + + void clear () + { + //Lee: + //The original was just too strange, though correct: + // TiXmlString().swap(*this); + //Instead use the quit & re-init: + quit(); + init(0,0); + } + + /* Function to reserve a big amount of data when we know we'll need it. Be aware that this + function DOES NOT clear the content of the TiXmlString if any exists. + */ + void reserve (size_type cap); + + TiXmlString& assign (const char* str, size_type len); + + TiXmlString& append (const char* str, size_type len); + + void swap (TiXmlString& other) + { + Rep* r = rep_; + rep_ = other.rep_; + other.rep_ = r; + } + + private: + + void init(size_type sz) { init(sz, sz); } + void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } + char* start() const { return rep_->str; } + char* finish() const { return rep_->str + rep_->size; } + + struct Rep + { + size_type size, capacity; + char str[1]; + }; + + void init(size_type sz, size_type cap) + { + if (cap) + { + // Lee: the original form: + // rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap)); + // doesn't work in some cases of new being overloaded. Switching + // to the normal allocation, although use an 'int' for systems + // that are overly picky about structure alignment. + const size_type bytesNeeded = sizeof(Rep) + cap; + const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); + rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] ); + + rep_->str[ rep_->size = sz ] = '\0'; + rep_->capacity = cap; + } + else + { + rep_ = &nullrep_; + } + } + + void quit() + { + if (rep_ != &nullrep_) + { + // The rep_ is really an array of ints. (see the allocator, above). + // Cast it back before delete, so the compiler won't incorrectly call destructors. + delete [] ( reinterpret_cast<int*>( rep_ ) ); + } + } + + Rep * rep_; + static Rep nullrep_; + +} ; + + +inline bool operator == (const TiXmlString & a, const TiXmlString & b) +{ + return ( a.length() == b.length() ) // optimization on some platforms + && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare +} +inline bool operator < (const TiXmlString & a, const TiXmlString & b) +{ + return strcmp(a.c_str(), b.c_str()) < 0; +} + +inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } +inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } +inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } +inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } + +inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } +inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } +inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } +inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } + +TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); +TiXmlString operator + (const TiXmlString & a, const char* b); +TiXmlString operator + (const char* a, const TiXmlString & b); + + +/* + TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. + Only the operators that we need for TinyXML have been developped. +*/ +class TiXmlOutStream : public TiXmlString +{ +public : + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const TiXmlString & in) + { + *this += in; + return *this; + } + + // TiXmlOutStream << operator. + TiXmlOutStream & operator << (const char * in) + { + *this += in; + return *this; + } + +} ; + +#endif // TIXML_STRING_INCLUDED +#endif // TIXML_USE_STL diff --git a/src/tinyxml/tinyxml.cpp b/src/tinyxml/tinyxml.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9c161dfcb934e855ff679998c34669bfdd66aa21 --- /dev/null +++ b/src/tinyxml/tinyxml.cpp @@ -0,0 +1,1886 @@ +/* +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. + +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. + +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. +*/ + +#include <ctype.h> + +#ifdef TIXML_USE_STL +#include <sstream> +#include <iostream> +#endif + +#include "tinyxml.h" + +FILE* TiXmlFOpen( const char* filename, const char* mode ); + +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 +} + +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; + } + } +} + + +TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() +{ + parent = 0; + type = _type; + firstChild = 0; + lastChild = 0; + prev = 0; + next = 0; +} + + +TiXmlNode::~TiXmlNode() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + 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; +} + + +void TiXmlNode::Clear() +{ + TiXmlNode* node = firstChild; + TiXmlNode* temp = 0; + + while ( node ) + { + temp = node; + node = node->next; + delete temp; + } + + firstChild = 0; + lastChild = 0; +} + + +TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) +{ + 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; + } + + node->parent = this; + + node->prev = lastChild; + node->next = 0; + + if ( lastChild ) + lastChild->next = node; + else + firstChild = node; // it was an empty list. + + 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; + + 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; +} + + +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; +} + + +TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) +{ + if ( !replaceThis ) + 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; + } + + TiXmlNode* node = withThis.Clone(); + if ( !node ) + return 0; + + node->next = replaceThis->next; + node->prev = replaceThis->prev; + + if ( replaceThis->next ) + replaceThis->next->prev = node; + else + lastChild = node; + + if ( replaceThis->prev ) + replaceThis->prev->next = node; + else + firstChild = node; + + delete replaceThis; + node->parent = this; + return node; +} + + +bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) +{ + if ( !removeThis ) { + return false; + } + + if ( removeThis->parent != this ) + { + assert( 0 ); + return false; + } + + if ( removeThis->next ) + removeThis->next->prev = removeThis->prev; + else + lastChild = removeThis->prev; + + if ( removeThis->prev ) + removeThis->prev->next = removeThis->next; + else + firstChild = removeThis->next; + + 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* 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* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const +{ + 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 ); + } +} + + +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* 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; +} + + +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; + } +} + +const TiXmlElement* TiXmlNode::FirstChildElement() const +{ + const TiXmlNode* node; + + 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; + + 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; + + 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; + + 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; + + for( node = this; node; node = node->parent ) + { + if ( node->ToDocument() ) + return node->ToDocument(); + } + return 0; +} + + +TiXmlElement::TiXmlElement (const char * _value) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} + + +#ifdef TIXML_USE_STL +TiXmlElement::TiXmlElement( const std::string& _value ) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +{ + firstChild = lastChild = 0; + value = _value; +} +#endif + + +TiXmlElement::TiXmlElement( const TiXmlElement& copy) + : TiXmlNode( TiXmlNode::TINYXML_ELEMENT ) +{ + firstChild = lastChild = 0; + copy.CopyTo( this ); +} + + +TiXmlElement& TiXmlElement::operator=( const TiXmlElement& base ) +{ + ClearThis(); + base.CopyTo( this ); + return *this; +} + + +TiXmlElement::~TiXmlElement() +{ + ClearThis(); +} + + +void TiXmlElement::ClearThis() +{ + 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; +} + + +#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; +} +#endif + + +const char* TiXmlElement::Attribute( const char* name, int* i ) const +{ + const TiXmlAttribute* attrib = attributeSet.Find( name ); + const char* result = 0; + + 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; + + 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; + + 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; + + 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 ); +} + + +int TiXmlElement::QueryUnsignedAttribute( const char* name, unsigned* value ) const +{ + 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 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; +} + + + +#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 ); +} +#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 ); +} + + +#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 ); +} +#endif + + +void TiXmlElement::SetAttribute( const char * name, int 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 ); + } +} +#endif + + +void TiXmlElement::SetDoubleAttribute( const char * name, double 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 ); + } +} +#endif + + +void TiXmlElement::SetAttribute( const char * cname, const char * 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 ); + } +} +#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() ); + } +} + + +void TiXmlElement::CopyTo( TiXmlElement* target ) const +{ + // 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() ); + } + + 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 ); +} + + +TiXmlNode* TiXmlElement::Clone() const +{ + TiXmlElement* clone = new TiXmlElement( Value() ); + if ( !clone ) + return 0; + + 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; +} + + +TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + ClearError(); +} + +TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} + + +#ifdef TIXML_USE_STL +TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + tabsize = 4; + useMicrosoftBOM = false; + value = documentName; + ClearError(); +} +#endif + + +TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT ) +{ + copy.CopyTo( this ); +} + + +TiXmlDocument& TiXmlDocument::operator=( const TiXmlDocument& copy ) +{ + Clear(); + copy.CopyTo( this ); + return *this; +} + + +bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) +{ + return LoadFile( Value(), encoding ); +} + + +bool TiXmlDocument::SaveFile() const +{ + return SaveFile( Value() ); +} + +bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) +{ + TIXML_STRING filename( _filename ); + value = filename; + + // 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; + } +} + +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(); +} + + +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; +} + + +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; + + 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 ); + + 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* TiXmlDocument::Clone() const +{ + TiXmlDocument* clone = new TiXmlDocument(); + if ( !clone ) + return 0; + + 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" ); + } +} + + +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 ); +} + + +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; +} + +/* +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; +} +*/ + +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; +} + +/* +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; +} +*/ + +void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + TIXML_STRING n, v; + + EncodeString( name, &n ); + EncodeString( value, &v ); + + if (value.find ('\"') == TIXML_STRING::npos) { + if ( cfile ) { + fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; + } + } + else { + if ( cfile ) { + fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); + } + if ( str ) { + (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; + } + } +} + + +int TiXmlAttribute::QueryIntValue( int* ival ) const +{ + 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; +} + +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); +} + +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); +} + +int TiXmlAttribute::IntValue() const +{ + return atoi (value.c_str ()); +} + +double TiXmlAttribute::DoubleValue() const +{ + return atof (value.c_str ()); +} + + +TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) +{ + copy.CopyTo( this ); +} + + +TiXmlComment& TiXmlComment::operator=( const TiXmlComment& base ) +{ + 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() ); +} + + +void TiXmlComment::CopyTo( TiXmlComment* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlComment::Clone() const +{ + TiXmlComment* clone = new TiXmlComment(); + + if ( !clone ) + return 0; + + 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() ); + } +} + + +void TiXmlText::CopyTo( TiXmlText* target ) const +{ + TiXmlNode::CopyTo( target ); + target->cdata = cdata; +} + + +bool TiXmlText::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlText::Clone() const +{ + TiXmlText* clone = 0; + clone = new TiXmlText( "" ); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlDeclaration::TiXmlDeclaration( const char * _version, + const char * _encoding, + const char * _standalone ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) +{ + 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 ) +{ + version = _version; + encoding = _encoding; + standalone = _standalone; +} +#endif + + +TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) + : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) +{ + copy.CopyTo( this ); +} + + +TiXmlDeclaration& TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) +{ + Clear(); + copy.CopyTo( this ); + return *this; +} + + +void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const +{ + if ( cfile ) fprintf( cfile, "<?xml " ); + if ( str ) (*str) += "<?xml "; + + if ( !version.empty() ) { + if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ()); + if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; } + } + if ( !encoding.empty() ) { + if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ()); + if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; } + } + if ( !standalone.empty() ) { + if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ()); + if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; } + } + if ( cfile ) fprintf( cfile, "?>" ); + if ( str ) (*str) += "?>"; +} + + +void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const +{ + TiXmlNode::CopyTo( target ); + + target->version = version; + target->encoding = encoding; + target->standalone = standalone; +} + + +bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlDeclaration::Clone() const +{ + TiXmlDeclaration* clone = new TiXmlDeclaration(); + + if ( !clone ) + return 0; + + 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() ); +} + + +void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const +{ + TiXmlNode::CopyTo( target ); +} + + +bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const +{ + return visitor->Visit( *this ); +} + + +TiXmlNode* TiXmlUnknown::Clone() const +{ + TiXmlUnknown* clone = new TiXmlUnknown(); + + if ( !clone ) + return 0; + + CopyTo( clone ); + return clone; +} + + +TiXmlAttributeSet::TiXmlAttributeSet() +{ + sentinel.next = &sentinel; + sentinel.prev = &sentinel; +} + + +TiXmlAttributeSet::~TiXmlAttributeSet() +{ + 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 + + addMe->next = &sentinel; + addMe->prev = sentinel.prev; + + sentinel.prev->next = addMe; + sentinel.prev = addMe; +} + +void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) +{ + 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. +} + + +#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; +} + +TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name ) +{ + 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; +} + + +TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name ) +{ + TiXmlAttribute* attrib = Find( _name ); + if ( !attrib ) { + attrib = new TiXmlAttribute(); + Add( attrib ); + attrib->SetName( _name ); + } + return attrib; +} + + +#ifdef TIXML_USE_STL +std::istream& operator>> (std::istream & in, TiXmlNode & base) +{ + TIXML_STRING tag; + tag.reserve( 8 * 1000 ); + base.StreamIn( &in, &tag ); + + base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); + return in; +} +#endif + + +#ifdef TIXML_USE_STL +std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out << printer.Str(); + + return out; +} + + +std::string& operator<< (std::string& out, const TiXmlNode& base ) +{ + TiXmlPrinter printer; + printer.SetStreamPrinting(); + base.Accept( &printer ); + out.append( printer.Str() ); + + return out; +} +#endif + + +TiXmlHandle TiXmlHandle::FirstChild() const +{ + 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 ); +} + + +TiXmlHandle TiXmlHandle::FirstChildElement() const +{ + 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 ); +} + + +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 ); +} + + +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 ); +} + + +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 ); +} + + +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 ); +} + + +bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) +{ + return true; +} + +bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) +{ + 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; +} + + +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; +} + + +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; +} + + +bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) +{ + DoIndent(); + declaration.Print( 0, 0, &buffer ); + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlComment& comment ) +{ + DoIndent(); + buffer += "<!--"; + buffer += comment.Value(); + buffer += "-->"; + DoLineBreak(); + return true; +} + + +bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) +{ + DoIndent(); + buffer += "<"; + buffer += unknown.Value(); + buffer += ">"; + DoLineBreak(); + return true; +} + diff --git a/src/tinyxml/tinyxml.h b/src/tinyxml/tinyxml.h new file mode 100644 index 0000000000000000000000000000000000000000..b3f08d658abb934b968d4ff57c97b7686b3ef207 --- /dev/null +++ b/src/tinyxml/tinyxml.h @@ -0,0 +1,1807 @@ +/* +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. + +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. + +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. +*/ + + +#define TIXML_USE_STL + +#ifndef TINYXML_INCLUDED +#define TINYXML_INCLUDED + +#ifdef _MSC_VER +#pragma warning( push ) +#pragma warning( disable : 4530 ) +#pragma warning( disable : 4786 ) +#endif + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +// Help out windows: +#if defined( _DEBUG ) && !defined( DEBUG ) +#define DEBUG +#endif + +#ifdef TIXML_USE_STL + #include <string> + #include <iostream> + #include <sstream> + #define TIXML_STRING std::string +#else + #include "tinystr.h" + #define TIXML_STRING TiXmlString +#endif + +// Deprecated library function hell. Compilers want to use the +// new safe versions. This probably doesn't fully address the problem, +// but it gets closer. There are too many compilers for me to fully +// test. If you get compilation troubles, undefine TIXML_SAFE +#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 + +class TiXmlDocument; +class TiXmlElement; +class TiXmlComment; +class TiXmlUnknown; +class TiXmlAttribute; +class TiXmlText; +class TiXmlDeclaration; +class TiXmlParsingData; + +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. +*/ +struct TiXmlCursor +{ + TiXmlCursor() { Clear(); } + void Clear() { row = col = -1; } + + 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(). + + 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. + + Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. + + You should never change the document from a callback. + + @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; } +}; + +// Only used by Attribute::Query functions +enum +{ + TIXML_SUCCESS, + TIXML_NO_ATTRIBUTE, + TIXML_WRONG_TYPE +}; + + +// Used by the parsing routines. +enum TiXmlEncoding +{ + TIXML_ENCODING_UNKNOWN, + TIXML_ENCODING_UTF8, + TIXML_ENCODING_LEGACY +}; + +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 +*/ +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; +}; + + +/** 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. +*/ +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. +}; + + +/** An attribute is a name-value pair. Elements have an arbitrary + 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. +*/ +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; +}; + + +/* 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. +*/ +class TiXmlAttributeSet +{ +public: + TiXmlAttributeSet(); + ~TiXmlAttributeSet(); + + void Add( TiXmlAttribute* attribute ); + void Remove( TiXmlAttribute* attribute ); + + const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + + TiXmlAttribute* Find( const char* _name ) const; + TiXmlAttribute* FindOrCreate( const char* _name ); + +# ifdef TIXML_USE_STL + TiXmlAttribute* Find( const std::string& _name ) const; + TiXmlAttribute* FindOrCreate( const std::string& _name ); +# 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) + + 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. +*/ +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; +}; + + +/** 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: + +}; + + +/** 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(). +*/ +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 +}; + + +/** In correct XML the declaration is the first entry in the file. + @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. + + 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 ) {} + +#ifdef TIXML_USE_STL + /// Constructor. + TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ); +#endif + + /// Construct. + TiXmlDeclaration( const char* _version, + const char* _encoding, + const char* _standalone ); + + TiXmlDeclaration( const TiXmlDeclaration& copy ); + TiXmlDeclaration& operator=( const TiXmlDeclaration& copy ); + + virtual ~TiXmlDeclaration() {} + + /// Version. Will return an empty string if none was found. + const char *Version() const { return version.c_str (); } + /// Encoding. Will return an empty string if none was found. + const char *Encoding() const { return encoding.c_str (); } + /// Is this a standalone document? + const char *Standalone() const { return standalone.c_str (); } + + /// Creates a copy of this Declaration and returns it. + virtual TiXmlNode* Clone() const; + // Print this declaration to a FILE stream. + virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; + +protected: + void CopyTo( TiXmlDeclaration* target ) const; + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +private: + + 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. + + DTD tags get thrown into TiXmlUnknowns. +*/ +class TiXmlUnknown : public TiXmlNode +{ +public: + TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} + virtual ~TiXmlUnknown() {} + + TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); } + TiXmlUnknown& operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); return *this; } + + /// Creates a copy of this Unknown and returns it. + virtual TiXmlNode* Clone() const; + // Print this Unknown to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; + +protected: + void CopyTo( TiXmlUnknown* target ) const; + + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + +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. +*/ +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. +}; + + +/** + 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; +}; + + +/** 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.) + + 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" ); + + 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; +}; + + +#ifdef _MSC_VER +#pragma warning( pop ) +#endif + +#endif diff --git a/src/tinyxml/tinyxmlerror.cpp b/src/tinyxml/tinyxmlerror.cpp new file mode 100644 index 0000000000000000000000000000000000000000..538c21d0bd95fb114e70636bc1a776937975a912 --- /dev/null +++ b/src/tinyxml/tinyxmlerror.cpp @@ -0,0 +1,52 @@ +/* +www.sourceforge.net/projects/tinyxml +Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +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: + +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. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include "tinyxml.h" + +// The goal of the seperate error file is to make the first +// step towards localization. tinyxml (currently) only supports +// english error messages, but the could now be translated. +// +// It also cleans up the code a bit. +// + +const char* TiXmlBase::errorString[ TiXmlBase::TIXML_ERROR_STRING_COUNT ] = +{ + "No error", + "Error", + "Failed to open file", + "Error parsing Element.", + "Failed to read Element name", + "Error reading Element value.", + "Error reading Attributes.", + "Error: empty tag.", + "Error reading end tag.", + "Error parsing Unknown.", + "Error parsing Comment.", + "Error parsing Declaration.", + "Error document empty.", + "Error null (0) or unexpected EOF found in input stream.", + "Error parsing CDATA.", + "Error when TiXmlDocument added to document, because TiXmlDocument can only be at the root.", +}; diff --git a/src/tinyxml/tinyxmlparser.cpp b/src/tinyxml/tinyxmlparser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a7e0137264ed4da6c19a6e75f34477c9761e8f3d --- /dev/null +++ b/src/tinyxml/tinyxmlparser.cpp @@ -0,0 +1,1639 @@ +/* +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. + +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. + +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. +*/ + +#include <ctype.h> +#include <stddef.h> +#include <assert.h> + +#include "tinyxml.h" + +//#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 +#endif + +// Note tha "PutString" hardcodes the same list. This +// is less flexible than it appears. Changing the entries +// or order will break putstring. +TiXmlBase::Entity TiXmlBase::entity[ TiXmlBase::NUM_ENTITY ] = +{ + { "&", 5, '&' }, + { "<", 4, '<' }, + { ">", 4, '>' }, + { """, 6, '\"' }, + { "'", 6, '\'' } +}; + +// Bunch of unicode info at: +// 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 + +const unsigned char TIXML_UTF_LEAD_0 = 0xefU; +const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; +const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + +const int TiXmlBase::utf8ByteTable[256] = +{ + // 0 1 2 3 4 5 6 7 8 9 a b c d e f + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte + 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid +}; + + +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]); + } +} + + +/*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 ); +// } +} + + +/*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 ); +// } +} + + +class TiXmlParsingData +{ + friend class TiXmlDocument; + public: + void Stamp( const char* now, TiXmlEncoding encoding ); + + const TiXmlCursor& Cursor() const { return cursor; } + + private: + // Only used by the document! + TiXmlParsingData( const char* start, int _tabsize, int row, int col ) + { + assert( start ); + stamp = start; + tabsize = _tabsize; + cursor.row = row; + cursor.col = col; + } + + TiXmlCursor cursor; + const char* stamp; + int tabsize; +}; + + +void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) +{ + assert( now ); + + // Do nothing if the tabsize is 0. + if ( tabsize < 1 ) + { + return; + } + + // Get the current row, column. + int row = cursor.row; + int col = cursor.col; + const char* p = stamp; + assert( p ); + + while ( p < now ) + { + // Treat p as unsigned, so we have a happy compiler. + const unsigned char* pU = (const unsigned char*)p; + + // Code contributed by Fletcher Dunn: (modified by lee) + switch (*pU) { + case 0: + // We *should* never get here, but in case we do, don't + // advance past the terminating null character, ever + return; + + case '\r': + // bump down to the next line + ++row; + col = 0; + // Eat the character + ++p; + + // Check for \r\n sequence, and treat this as a single character + if (*p == '\n') { + ++p; + } + break; + + case '\n': + // bump down to the next line + ++row; + col = 0; + + // Eat the character + ++p; + + // Check for \n\r sequence, and treat this as a single + // character. (Yes, this bizarre thing does occur still + // on some arcane platforms...) + if (*p == '\r') { + ++p; + } + break; + + case '\t': + // Eat the character + ++p; + + // Skip to next tab stop + col = (col / tabsize + 1) * tabsize; + break; + + case TIXML_UTF_LEAD_0: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( *(p+1) && *(p+2) ) + { + // In these cases, don't advance the column. These are + // 0-width spaces. + if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) + p += 3; + else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) + p += 3; + else + { p +=3; ++col; } // A normal character. + } + } + else + { + ++p; + ++col; + } + break; + + default: + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // Eat the 1 to 4 byte utf8 character. + int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; + if ( step == 0 ) + step = 1; // Error case from bad encoding, but handle gracefully. + p += step; + + // Just advance one column, of course. + ++col; + } + else + { + ++p; + ++col; + } + break; + } + } + cursor.row = row; + cursor.col = col; + assert( cursor.row >= -1 ); + assert( cursor.col >= -1 ); + stamp = p; + assert( stamp ); +} + + +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; +} + +#ifdef TIXML_USE_STL +/*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) +{ + 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; + + *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; +} +#endif + +// One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The +// "assign" optimization removes over 10% of the execution time. +// +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; +} + +const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) +{ + // Presume an entity, and pull it out. + TIXML_STRING ent; + int i; + *length = 0; + + if ( *(p+1) && *(p+1) == '#' && *(p+2) ) + { + unsigned long ucs = 0; + ptrdiff_t delta = 0; + unsigned mult = 1; + + if ( *(p+2) == 'x' ) + { + // Hexadecimal. + if ( !*(p+3) ) return 0; + + const char* q = p+3; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != 'x' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else if ( *q >= 'a' && *q <= 'f' ) + ucs += mult * (*q - 'a' + 10); + else if ( *q >= 'A' && *q <= 'F' ) + ucs += mult * (*q - 'A' + 10 ); + else + return 0; + mult *= 16; + --q; + } + } + else + { + // Decimal. + if ( !*(p+2) ) return 0; + + const char* q = p+2; + q = strchr( q, ';' ); + + if ( !q || !*q ) return 0; + + delta = q-p; + --q; + + while ( *q != '#' ) + { + if ( *q >= '0' && *q <= '9' ) + ucs += mult * (*q - '0'); + else + return 0; + mult *= 10; + --q; + } + } + if ( encoding == TIXML_ENCODING_UTF8 ) + { + // convert the UCS to UTF-8 + ConvertUTF32ToUTF8( ucs, value, length ); + } + else + { + *value = (char)ucs; + *length = 1; + } + return p + delta + 1; + } + + // Now try to match it. + for( i=0; i<NUM_ENTITY; ++i ) + { + if ( strncmp( entity[i].str, p, entity[i].strLength ) == 0 ) + { + assert( strlen( entity[i].str ) == entity[i].strLength ); + *value = entity[i].chr; + *length = 1; + return ( p + entity[i].strLength ); + } + } + + // So it wasn't an entity, its unrecognized, or something like that. + *value = *p; // Don't put back the last one, since we return it! + //*length = 1; // Leave unrecognized entities - this doesn't really work. + // Just writes strange XML. + return p+1; +} + + +bool TiXmlBase::StringEqual( const char* p, + 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; +} + +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; +} + +#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 ); +} + +#endif + +const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) +{ + ClearError(); + + // Parse away, at the document level. Since a document + // contains nothing but other tags, most of what happens + // here is skipping white space. + if ( !p || !*p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + // Note that, for a document, this needs to come + // before the while space skip, so that parsing + // starts from the pointer we are given. + location.Clear(); + if ( prevData ) + { + location.row = prevData->cursor.row; + location.col = prevData->cursor.col; + } + else + { + location.row = 0; + location.col = 0; + } + TiXmlParsingData data( p, TabSize(), location.row, location.col ); + location = data.Cursor(); + + if ( encoding == TIXML_ENCODING_UNKNOWN ) + { + // Check for the Microsoft UTF-8 lead bytes. + const unsigned char* pU = (const unsigned char*)p; + if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 + && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 + && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) + { + encoding = TIXML_ENCODING_UTF8; + useMicrosoftBOM = true; + } + } + + p = SkipWhiteSpace( p, encoding ); + if ( !p ) + { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); + return 0; + } + + while ( p && *p ) + { + TiXmlNode* node = Identify( p, encoding ); + if ( node ) + { + p = node->Parse( p, &data, encoding ); + LinkEndChild( node ); + } + else + { + break; + } + + // Did we get encoding info? + if ( encoding == TIXML_ENCODING_UNKNOWN + && node->ToDeclaration() ) + { + TiXmlDeclaration* dec = node->ToDeclaration(); + const char* enc = dec->Encoding(); + assert( enc ); + + if ( *enc == 0 ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; + else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) + encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice + else + encoding = TIXML_ENCODING_LEGACY; + } + + p = SkipWhiteSpace( p, encoding ); + } + + // Was this empty? + if ( !firstChild ) { + SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); + return 0; + } + + // All is well. + return p; +} + +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(); + } +} + + +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; +} + +#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. + } + } + } +} +#endif + +const char* TiXmlElement::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + p = SkipWhiteSpace( p, encoding ); + TiXmlDocument* document = GetDocument(); + + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, 0, 0, encoding ); + return 0; + } + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + + if ( *p != '<' ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, p, data, encoding ); + return 0; + } + + p = SkipWhiteSpace( p+1, encoding ); + + // Read the name. + const char* pErr = p; + + p = ReadName( p, &value, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, pErr, data, encoding ); + return 0; + } + + TIXML_STRING endTag ("</"); + endTag += value; + + // Check for and read attributes. Also look for an empty + // tag or an end tag. + while ( p && *p ) + { + pErr = p; + p = SkipWhiteSpace( p, encoding ); + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); + return 0; + } + if ( *p == '/' ) + { + ++p; + // Empty tag. + if ( *p != '>' ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY, p, data, encoding ); + return 0; + } + return (p+1); + } + else if ( *p == '>' ) + { + // Done with attributes (if there were any.) + // Read the value -- which can include other + // elements -- read the end tag, and return. + ++p; + p = ReadValue( p, data, encoding ); // Note this is an Element method, and will set the error if one happens. + if ( !p || !*p ) { + // We were looking for the end tag, but found nothing. + // Fix for [ 1663758 ] Failure to report error on bad XML + if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); + return 0; + } + + // We should find the end tag now + // note that: + // </foo > and + // </foo> + // are both valid end tags. + if ( StringEqual( p, endTag.c_str(), false, encoding ) ) + { + p += endTag.length(); + p = SkipWhiteSpace( p, encoding ); + if ( p && *p && *p == '>' ) { + ++p; + return p; + } + if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); + return 0; + } + else + { + if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG, p, data, encoding ); + return 0; + } + } + else + { + // Try to read an attribute: + TiXmlAttribute* attrib = new TiXmlAttribute(); + if ( !attrib ) + { + return 0; + } + + attrib->SetDocument( document ); + pErr = p; + p = attrib->Parse( p, data, encoding ); + + if ( !p || !*p ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding ); + delete attrib; + return 0; + } + + // Handle the strange case of double attributes: + #ifdef TIXML_USE_STL + TiXmlAttribute* node = attributeSet.Find( attrib->NameTStr() ); + #else + TiXmlAttribute* node = attributeSet.Find( attrib->Name() ); + #endif + if ( node ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT, pErr, data, encoding ); + delete attrib; + return 0; + } + + attributeSet.Add( attrib ); + } + } + return p; +} + + +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; +} + + +#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; + } + } +} +#endif + + +const char* TiXmlUnknown::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + TiXmlDocument* document = GetDocument(); + p = SkipWhiteSpace( p, encoding ); + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + if ( !p || !*p || *p != '<' ) + { + if ( document ) document->SetError( TIXML_ERROR_PARSING_UNKNOWN, p, data, encoding ); + return 0; + } + ++p; + value = ""; + + while ( p && *p && *p != '>' ) + { + value += *p; + ++p; + } + + if ( !p ) + { + if ( document ) + document->SetError( TIXML_ERROR_PARSING_UNKNOWN, 0, 0, encoding ); + } + if ( p && *p == '>' ) + return p+1; + return p; +} + +#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; + } + } +} +#endif + + +const char* TiXmlComment::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) +{ + TiXmlDocument* document = GetDocument(); + value = ""; + + p = SkipWhiteSpace( p, encoding ); + + if ( data ) + { + data->Stamp( p, encoding ); + location = data->Cursor(); + } + const char* startTag = "<!--"; + const char* endTag = "-->"; + + if ( !StringEqual( p, startTag, false, encoding ) ) + { + if ( document ) + document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); + return 0; + } + p += strlen( startTag ); + + // [ 1475201 ] TinyXML parses entities in comments + // Oops - ReadText doesn't work, because we don't want to parse the entities. + // p = ReadText( p, &value, false, endTag, false, encoding ); + // + // from the XML spec: + /* + [Definition: Comments may appear anywhere in a document outside other markup; in addition, + they may appear within the document type declaration at places allowed by the grammar. + They are not part of the document's character data; an XML processor MAY, but need not, + make it possible for an application to retrieve the text of comments. For compatibility, + the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity + references MUST NOT be recognized within comments. + + An example of a comment: + + <!-- declarations for <head> & <body> --> + */ + + value = ""; + // Keep all the white space. + while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) + { + value.append( p, 1 ); + ++p; + } + if ( p && *p ) + p += strlen( endTag ); + + return p; +} + + +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; +} + +#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; + } + } + } +} +#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; + } +} + +#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; + } + } +} +#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; +} + +bool TiXmlText::Blank() const +{ + for ( unsigned i=0; i<value.length(); i++ ) + if ( !IsWhiteSpace( value[i] ) ) + return false; + return true; +} + diff --git a/src/travisto.cpp b/src/travisto.cpp index 4891ec1651a139227fc5698f1a00f40718e0fef4..d6df14daaaaed7bf176ca883889f17eb8f4a12b4 100644 --- a/src/travisto.cpp +++ b/src/travisto.cpp @@ -45,11 +45,8 @@ #include "SimpleVisualisationWindow.h" #include "geometry/FacilityGeometry.h" -#include "geometry/jul/Building.h" -#include "geometry/pg3/CBuilding.h" - -#include <QtGui/QMessageBox> +#include <QMessageBox> #include <QtXml/QDomDocument> #include <QTime> #include <QApplication> @@ -286,7 +283,7 @@ void TraVisTo::slotHelpAbout() { void TraVisTo::slotNetworkSettings() { bool ok; - int port = QInputDialog::getInteger(this, tr("input a port "), tr( + int port = QInputDialog::getInt(this, tr("input a port "), tr( "port(default to 8081):"), 8989, 5000, 65355, 1, &ok); if (ok) { @@ -418,6 +415,7 @@ bool TraVisTo::slotLoadFile() { // This function is only used in online Mode FacilityGeometry* TraVisTo::parseGeometry(QDomNode geoNode){ + cout<<"parsing the geo"<<endl; if(geoNode.isNull()) return NULL; //check if there is a tag 'file' there in @@ -426,17 +424,12 @@ FacilityGeometry* TraVisTo::parseGeometry(QDomNode geoNode){ if(!fileName.isEmpty()) { - if(fileName.endsWith(".jul",Qt::CaseInsensitive)) - { - //should be a file name - //return parseGeometryJUL(fileName); - SaxParser::parseGeometryJUL(fileName,geometry); - } - else if (fileName.endsWith(".pg3",Qt::CaseInsensitive)) + if (fileName.endsWith(".xml",Qt::CaseInsensitive)) { + //cout<<"good bye"<<endl; exit(0); //should be a file name //return parseGeometryPG3(fileName); - SaxParser::parseGeometryPG3(fileName,geometry); + //SaxParser::parseGeometryPG3(fileName,geometry); } else if (fileName.endsWith(".trav",Qt::CaseInsensitive)) { @@ -560,7 +553,6 @@ bool TraVisTo::addPedestrianGroup(int groupID,QString fileName){ "F:\\workspace\\TraVisTo\\data", "Visualisation Files (*.dat *.trav *.xml *.pg3 *.jul);;All Files (*.*)"); - if (fileName.isNull()) { return false; } @@ -568,20 +560,8 @@ bool TraVisTo::addPedestrianGroup(int groupID,QString fileName){ //FacilityGeometry* geometry=NULL; FacilityGeometry* geometry = visualisationThread->getGeometry(); - //reading and parsing - if(fileName.endsWith(".jul",Qt::CaseInsensitive)) - { - //geometry=parseGeometryJUL(fileName); - SaxParser::parseGeometryJUL(fileName,geometry); - } - else if (fileName.endsWith(".pg3",Qt::CaseInsensitive)) - { - //geometry=parseGeometryPG3(fileName); - SaxParser::parseGeometryPG3(fileName,geometry); - } - // if xml is detected, just load and show the geometry then exit - else if(fileName.endsWith(".xml",Qt::CaseInsensitive)){ + if(fileName.endsWith(".xml",Qt::CaseInsensitive)){ SaxParser::parseGeometryXMLV04(fileName,geometry); //slotLoadParseShowGeometry(fileName); //return false; @@ -1471,7 +1451,7 @@ void TraVisTo::slotSetCameraPerspectiveToSide(){ void TraVisTo::slotSetCameraPerspectiveToVirtualAgent(){ bool ok=false; - int agent = QInputDialog::getInteger(this, tr("choose the agent you want to see the scene through"), tr( + int agent = QInputDialog::getInt(this, tr("choose the agent you want to see the scene through"), tr( "agent ID(default to 1):"),1,1,500, 1, &ok); if (ok) { diff --git a/src/travisto.h b/src/travisto.h index ad73647bc331937be1cbf5a8e9f2d5eb42a0ce12..a61f1df63f7bd3f1ce7a9b0a77c11a9e3d101d4f 100644 --- a/src/travisto.h +++ b/src/travisto.h @@ -35,7 +35,7 @@ #include "ui_travisto.h" -#include <QtGui/QMainWindow> +#include <QMainWindow> #include <vector>