[Positioning] TopologyReaderCSV: read waypoints
Stock: add Waypoint list and support functions. Waypoint: - Use an unordered_set instead of a vector for the Building list. - Add functions add_building(), add_buildings() and remove_building(). - Add operator string(). cfg/waypoints.csv: change format (add building name).
This commit is contained in:
parent
208c989c53
commit
14902181af
|
@ -123,7 +123,10 @@ $(OBJ_DIR)/inputdatareader.o: \
|
|||
$(OBJ_DIR)/configuration.o \
|
||||
$(OBJ_DIR)/posexcept.o
|
||||
$(OBJ_DIR)/topologyreadercsv.o: \
|
||||
$(OBJ_DIR)/textfilereader.o
|
||||
$(OBJ_DIR)/csvfilereader.o \
|
||||
$(OBJ_DIR)/area.o \
|
||||
$(OBJ_DIR)/waypoint.o \
|
||||
$(OBJ_DIR)/stock.o
|
||||
$(OBJ_DIR)/referencepoint.o: \
|
||||
$(OBJ_DIR)/point3d.o
|
||||
$(OBJ_DIR)/waypoint.o: \
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
|
||||
- Hachages
|
||||
° Regrouper les surcharges de hash_value() dans un fichier
|
||||
d'en-tête dédié.
|
||||
° Éventuellement, ce fichier d'en-tête pourrait être utilisé comme
|
||||
une interface et inclure directement <unordered_set> et
|
||||
<unordered_map>.
|
||||
|
||||
- Tests unitaires
|
||||
° Finir le test de InputDataReader.
|
||||
° Finir le test de Input.
|
||||
|
@ -49,8 +56,6 @@
|
|||
- « C++ en action »
|
||||
° Espaces de noms ? 109
|
||||
° Réserver l'espace mémoire des vector avec reserve(). 217
|
||||
° Utiliser hash_map (maintenant unordered_map) plutôt que map s'il
|
||||
n'y a pas besoin de trier. 232
|
||||
° Copie de conteneur vers un flux (cas de certains operator<<). 275
|
||||
|
||||
- « Coder proprement »
|
||||
|
|
|
@ -1,122 +1,124 @@
|
|||
# Liste des points de passage.
|
||||
# Chaque ligne définit les trois coordonnées d'un point, de la forme :
|
||||
# X;Y;Z
|
||||
# X;Y;Z;Nom du bâtiment 1;…;Nom du bâtiment n
|
||||
# Chaque point doit appartenir au moins à un bâtiment.
|
||||
|
||||
# Note : pour les zones appartenant à la même pièce non-convexe (ex : Couloir N0 A et Couloir N0 B), on définit un point tous les 1,50 m.
|
||||
# Note : pour les zones appartenant à la même pièce non-convexe (ex :
|
||||
# Couloir N0 A et Couloir N0 B), on définit un point tous les 1,50 m.
|
||||
# Idem pour les portes très larges.
|
||||
|
||||
### Rez-de-chaussée ###
|
||||
|
||||
# 0140
|
||||
6.05;6.50;0.00
|
||||
6.05;6.50;0.00;Numerica
|
||||
|
||||
# 0130
|
||||
6.05;7.50;0.00
|
||||
6.05;7.50;0.00;Numerica
|
||||
|
||||
# 0120
|
||||
6.05;13.50;0.00
|
||||
6.05;13.50;0.00;Numerica
|
||||
|
||||
# 0130 / 0120
|
||||
3.00;10.88;0.00
|
||||
3.00;10.88;0.00;Numerica
|
||||
|
||||
# 0110
|
||||
6.05;14.50;0.00
|
||||
6.05;14.50;0.00;Numerica
|
||||
|
||||
# 0100
|
||||
6.05;21.00;0.00
|
||||
6.05;21.00;0.00;Numerica
|
||||
|
||||
# 0090
|
||||
6.05;22.25;0.00
|
||||
6.05;22.25;0.00;Numerica
|
||||
|
||||
# 0080
|
||||
6.05;28.50;0.00
|
||||
6.05;28.50;0.00;Numerica
|
||||
|
||||
# 0070
|
||||
6.05;29.50;0.00
|
||||
6.05;29.50;0.00;Numerica
|
||||
|
||||
# WC N0
|
||||
8.20;5.00;0.00
|
||||
8.20;5.00;0.00;Numerica
|
||||
|
||||
# 0085
|
||||
8.20;8.50;0.00
|
||||
8.20;8.50;0.00;Numerica
|
||||
|
||||
# 0075
|
||||
8.20;9.50;0.00
|
||||
8.20;9.50;0.00;Numerica
|
||||
|
||||
# Couloir N0 A / B
|
||||
8.20;11.50;0.00
|
||||
8.20;13.00;0.00
|
||||
8.20;14.50;0.00
|
||||
8.20;16.00;0.00
|
||||
8.20;11.50;0.00;Numerica
|
||||
8.20;13.00;0.00;Numerica
|
||||
8.20;14.50;0.00;Numerica
|
||||
8.20;16.00;0.00;Numerica
|
||||
|
||||
# Couloir N0 A / C
|
||||
8.20;23.70;0.00
|
||||
8.20;23.70;0.00;Numerica
|
||||
|
||||
# Palier N0
|
||||
7.50;3.70;0.00
|
||||
7.50;3.70;0.00;Numerica
|
||||
|
||||
|
||||
### Escaliers N0 / N1 ###
|
||||
|
||||
# Couloir N0 C / Escalier NO-N1 A
|
||||
8.95;22.60;0.00
|
||||
8.95;22.60;0.00;Numerica
|
||||
|
||||
# Escalier NO-N1 A / Couloir N1 B
|
||||
8.95;16.50;3.00
|
||||
8.95;16.50;3.00;Numerica
|
||||
|
||||
# Palier NO / Escalier N0-N1 B1
|
||||
5.00;1.25;0.00
|
||||
5.00;1.25;0.00;Numerica
|
||||
|
||||
# Escalier N0-N1 B1 / Escalier N0-N1 B palier
|
||||
2.50;1.25;1.50
|
||||
2.50;1.25;1.50;Numerica
|
||||
|
||||
# Escalier N0-N1 B palier / Escalier N0-N1 B2
|
||||
2.50;2.75;1.50
|
||||
2.50;2.75;1.50;Numerica
|
||||
|
||||
# Escalier N0-N1 B2 / Palier N1
|
||||
5.00;2.75;3.00
|
||||
5.00;2.75;3.00;Numerica
|
||||
|
||||
|
||||
### Premier étage ###
|
||||
|
||||
# 1100
|
||||
6.05;6.50;3.00
|
||||
6.05;6.50;3.00;Numerica
|
||||
|
||||
# 0190
|
||||
6.05;7.50;3.00
|
||||
6.05;7.50;3.00;Numerica
|
||||
|
||||
# 0180
|
||||
6.05;13.50;3.00
|
||||
6.05;13.50;3.00;Numerica
|
||||
|
||||
# 0190 / 0180
|
||||
3.00;10.88;3.00
|
||||
3.00;10.88;3.00;Numerica
|
||||
|
||||
# 1070
|
||||
6.05;14.50;3.00
|
||||
6.05;14.50;3.00;Numerica
|
||||
|
||||
# 1060
|
||||
6.05;21.00;3.00
|
||||
6.05;21.00;3.00;Numerica
|
||||
|
||||
# 1050
|
||||
6.05;27.75;3.00
|
||||
6.05;27.75;3.00;Numerica
|
||||
|
||||
# WC N1
|
||||
8.20;5.00;3.00
|
||||
8.20;5.00;3.00;Numerica
|
||||
|
||||
# 1105
|
||||
8.20;9.50;3.00
|
||||
8.20;9.50;3.00;Numerica
|
||||
|
||||
# 1095
|
||||
8.20;26.00;3.00
|
||||
8.20;26.00;3.00;Numerica
|
||||
|
||||
# Couloir N1 A / B
|
||||
8.20;11.50;3.00
|
||||
8.20;13.00;3.00
|
||||
8.20;14.50;3.00
|
||||
8.20;16.00;3.00
|
||||
8.20;11.50;3.00;Numerica
|
||||
8.20;13.00;3.00;Numerica
|
||||
8.20;14.50;3.00;Numerica
|
||||
8.20;16.00;3.00;Numerica
|
||||
|
||||
# Couloir N1 A / C
|
||||
8.20;23.70;3.00
|
||||
8.20;23.70;3.00;Numerica
|
||||
|
||||
# Palier N1
|
||||
7.50;3.70;3.00
|
||||
7.50;3.70;3.00;Numerica
|
||||
|
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "building.hh"
|
||||
#include "area.hh"
|
||||
#include "waypoint.hh"
|
||||
#include "stock.hh"
|
||||
|
||||
|
||||
using namespace std ;
|
||||
|
@ -28,11 +29,7 @@ Building::~Building()
|
|||
// Empty Waypoint list
|
||||
for (unordered_set<Waypoint*>::const_iterator i = waypoints.begin() ;
|
||||
i != waypoints.end() ; ++i)
|
||||
{
|
||||
// Delete current waypoint only if it is not linked to another building
|
||||
if ((*i)->get_buildings().size() <= 1)
|
||||
delete *i ;
|
||||
}
|
||||
Stock::waypoint_remove_building(**i, this) ;
|
||||
waypoints.clear() ;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,8 +43,12 @@ void InputDataReader::initialise_topology_media()
|
|||
void InputDataReader::initialise_topology_csv()
|
||||
{
|
||||
if (! Configuration::is_configured("data-input.areas-csv-file"))
|
||||
throw no_topology_input_csv_file() ;
|
||||
throw no_topology_input_csv_file("areas") ;
|
||||
|
||||
if (! Configuration::is_configured("data-input.waypoints-csv-file"))
|
||||
throw no_topology_input_csv_file("waypoints") ;
|
||||
|
||||
TopologyReaderCSV(
|
||||
Configuration::string_value("data-input.areas-csv-file")) ;
|
||||
Configuration::string_value("data-input.areas-csv-file"),
|
||||
Configuration::string_value("data-input.waypoints-csv-file")) ;
|
||||
}
|
||||
|
|
|
@ -33,9 +33,11 @@ topology_input_medium_type_unknown(const string &medium_name) throw():
|
|||
" » is unknown!") {}
|
||||
|
||||
|
||||
no_topology_input_csv_file::no_topology_input_csv_file() throw():
|
||||
no_topology_input_csv_file::
|
||||
no_topology_input_csv_file(const string &type) throw():
|
||||
posexcept(
|
||||
"No topologyinput CSV file specified in the configuration!") {}
|
||||
"No topology input CSV file specified in the configuration for "
|
||||
+ type + "!") {}
|
||||
|
||||
|
||||
malformed_topology::
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
class no_topology_input_csv_file: public posexcept
|
||||
{
|
||||
public:
|
||||
no_topology_input_csv_file(void) throw() ;
|
||||
no_topology_input_csv_file(const std::string &type) throw() ;
|
||||
} ;
|
||||
|
||||
|
||||
|
|
|
@ -6,17 +6,26 @@ using std::tr1::unordered_map ;
|
|||
using std::tr1::unordered_set ;
|
||||
|
||||
|
||||
/// Hash function, required to put ReferencePoint in a set
|
||||
size_t hash_value(const ReferencePoint &object)
|
||||
/* *** Hash functions, required to put points in a set *** */
|
||||
|
||||
inline size_t hash_value(const ReferencePoint &object)
|
||||
{
|
||||
return boost::hash_value(static_cast<string>(object)) ;
|
||||
}
|
||||
|
||||
inline size_t hash_value(const Point3D &object)
|
||||
{
|
||||
return boost::hash_value(static_cast<string>(object)) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* *** Attribute definitions *** */
|
||||
|
||||
unordered_map<string, Building> Stock::buildings ;
|
||||
|
||||
unordered_map<Point3D, Waypoint> Stock::waypoints ;
|
||||
|
||||
unordered_map<string, Mobile> Stock::mobiles ;
|
||||
|
||||
unordered_map<string, AccessPoint> Stock::aps ;
|
||||
|
@ -63,6 +72,36 @@ const Building& Stock::get_building(const string &name)
|
|||
}
|
||||
|
||||
|
||||
const Waypoint& Stock::
|
||||
find_create_waypoint(const Point3D &point)
|
||||
{
|
||||
unordered_map<Point3D, Waypoint>::const_iterator i =
|
||||
waypoints.find(point) ;
|
||||
if (i != waypoints.end())
|
||||
return i->second ;
|
||||
|
||||
Waypoint &waypoint = waypoints[point] ;
|
||||
waypoint.set_coordinates(point) ;
|
||||
return waypoint ;
|
||||
}
|
||||
|
||||
|
||||
void Stock::waypoint_remove_building(const Waypoint &point,
|
||||
const Building *building)
|
||||
{
|
||||
unordered_map<Point3D, Waypoint>::iterator i =
|
||||
waypoints.find(point) ;
|
||||
|
||||
Waypoint *waypoint = const_cast<Waypoint*>(&i->second) ;
|
||||
waypoint->remove_building(building) ;
|
||||
|
||||
// If the Waypoint is not linked to any Building any more, we
|
||||
// delete it
|
||||
if (waypoint->get_1st_building() == NULL)
|
||||
waypoints.erase(i) ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param mac The MAC address of the Mobile to search for.
|
||||
* It must be a valid MAC address, as no check is performed.
|
||||
|
@ -131,7 +170,7 @@ const ReferencePoint& Stock::
|
|||
find_create_reference_point(const ReferencePoint &point)
|
||||
{
|
||||
// unordered_set::insert() do all the job: see the documentation at
|
||||
// http://www.boost.org/doc/libs/1_41_0/doc/html/boost/unordered_set.html
|
||||
// http://boost.org/doc/libs/1_42_0/doc/html/boost/unordered_set.html
|
||||
pair<unordered_set<ReferencePoint>::iterator, bool> ret =
|
||||
reference_points.insert(point) ;
|
||||
return *ret.first ;
|
||||
|
@ -150,6 +189,12 @@ find_create_calibration_request(const CalibrationRequest &request)
|
|||
void Stock::clear()
|
||||
{
|
||||
buildings.clear() ;
|
||||
|
||||
// Waypoints are normally deleted in Building::~Building(), so we must
|
||||
// not clear waypoints before buildings, but we clear it *after*, just
|
||||
// in case.
|
||||
waypoints.clear() ;
|
||||
|
||||
mobiles.clear() ;
|
||||
aps.clear() ;
|
||||
reference_points.clear() ;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define _OWLPS_POSITIONING_STOCK_HH_
|
||||
|
||||
#include "building.hh"
|
||||
#include "waypoint.hh"
|
||||
#include "mobile.hh"
|
||||
#include "accesspoint.hh"
|
||||
#include "referencepoint.hh"
|
||||
|
@ -17,6 +18,9 @@ private:
|
|||
/// List of known Building
|
||||
static std::tr1::unordered_map<std::string, Building> buildings ;
|
||||
|
||||
/// List of known Waypoint
|
||||
static std::tr1::unordered_map<Point3D, Waypoint> waypoints ;
|
||||
|
||||
/// List of known Mobile
|
||||
static std::tr1::unordered_map<std::string, Mobile> mobiles ;
|
||||
|
||||
|
@ -35,6 +39,18 @@ public:
|
|||
/// Look for a Building and create it if it does not exist
|
||||
static const Building& find_create_building(const std::string &name) ;
|
||||
|
||||
/// Look for a Waypoint and add it if it does not exist
|
||||
static const Waypoint&
|
||||
find_create_waypoint(const Waypoint &point) ;
|
||||
/// \brief Look for a Waypoint from its coordinates and add it if it
|
||||
/// does not exist
|
||||
static const Waypoint&
|
||||
find_create_waypoint(const Point3D &point) ;
|
||||
/// \brief Delete a Building from the building list of a Waypoint;
|
||||
/// delete the Waypoint if it is not linked to any Building any more
|
||||
static void waypoint_remove_building(const Waypoint &point,
|
||||
const Building *building) ;
|
||||
|
||||
/// Read the Mobile corresponding to a given MAC address
|
||||
static const Mobile& get_mobile(const std::string &mac) ;
|
||||
/// Look for a Mobile and create it if it does not exist
|
||||
|
@ -66,6 +82,17 @@ public:
|
|||
/* *** Accessors *** */
|
||||
|
||||
|
||||
inline const Waypoint& Stock::
|
||||
find_create_waypoint(const Waypoint &point)
|
||||
{
|
||||
Waypoint& found =
|
||||
const_cast<Waypoint&>(
|
||||
find_create_waypoint(static_cast<Point3D>(point))) ;
|
||||
found.add_buildings(point) ;
|
||||
return found ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If the Mobile corresponding to \em mac does not exist, it is created.
|
||||
* @param mac The MAC address of the Mobile to search for. It must be a
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#include "topologyreadercsv.hh"
|
||||
#include "posexcept.hh"
|
||||
#include "stock.hh"
|
||||
#include "point3d.hh"
|
||||
#include "area.hh"
|
||||
#include "waypoint.hh"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
|
@ -11,8 +11,9 @@ using namespace std ;
|
|||
/* *** Constructors *** */
|
||||
|
||||
|
||||
TopologyReaderCSV::TopologyReaderCSV(const string &filename):
|
||||
file(filename)
|
||||
TopologyReaderCSV::TopologyReaderCSV(
|
||||
const string &areas_file_name, const string &waypoints_file_name):
|
||||
areas_file(areas_file_name), waypoints_file(waypoints_file_name)
|
||||
{
|
||||
read_topology() ;
|
||||
}
|
||||
|
@ -24,32 +25,58 @@ TopologyReaderCSV::TopologyReaderCSV(const string &filename):
|
|||
|
||||
void TopologyReaderCSV::read_topology()
|
||||
{
|
||||
while (file.next_line())
|
||||
process_line() ;
|
||||
while (areas_file.next_line())
|
||||
process_area_line() ;
|
||||
|
||||
while (waypoints_file.next_line())
|
||||
process_waypoint_line() ;
|
||||
}
|
||||
|
||||
|
||||
void TopologyReaderCSV::process_line()
|
||||
void TopologyReaderCSV::process_area_line()
|
||||
{
|
||||
string building_name ;
|
||||
if (! file.read_field(building_name))
|
||||
if (! areas_file.read_field(building_name))
|
||||
throw malformed_topology("Cannot read building name!") ;
|
||||
Building &building = const_cast<Building&>(
|
||||
Stock::find_create_building(building_name)) ;
|
||||
|
||||
string name ;
|
||||
if (! file.read_field(name))
|
||||
if (! areas_file.read_field(name))
|
||||
throw malformed_topology("Cannot read area name!") ;
|
||||
|
||||
Point3D p_min(read_point()) ;
|
||||
Point3D p_max(read_point()) ;
|
||||
Point3D p_min(read_point(areas_file)) ;
|
||||
Point3D p_max(read_point(areas_file)) ;
|
||||
|
||||
Area *area = new Area(&building, name, p_min, p_max) ;
|
||||
building.add_area(area) ;
|
||||
}
|
||||
|
||||
|
||||
Point3D TopologyReaderCSV::read_point()
|
||||
void TopologyReaderCSV::process_waypoint_line()
|
||||
{
|
||||
Point3D coordinates(read_point(waypoints_file)) ;
|
||||
Waypoint &waypoint_ref =
|
||||
const_cast<Waypoint&>(Stock::find_create_waypoint(coordinates)) ;
|
||||
|
||||
vector<Building*> buildings ;
|
||||
string building_name ;
|
||||
while (waypoints_file.read_field(building_name))
|
||||
buildings.push_back(const_cast<Building*>(
|
||||
&Stock::find_create_building(building_name))) ;
|
||||
if (buildings.empty())
|
||||
throw malformed_topology("Cannot read building name!") ;
|
||||
|
||||
for (vector<Building*>::iterator i = buildings.begin() ;
|
||||
i != buildings.end() ; ++i)
|
||||
{
|
||||
waypoint_ref.add_building(*i) ;
|
||||
(*i)->add_waypoint(&waypoint_ref) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Point3D TopologyReaderCSV::read_point(CSVFileReader &file)
|
||||
{
|
||||
float coord[3] ;
|
||||
for (unsigned int i = 0 ; i < 3 ; ++i)
|
||||
|
|
|
@ -7,22 +7,29 @@ class Point3D ;
|
|||
|
||||
#include <string>
|
||||
|
||||
/// Reads and registers to the Stock an Area list from a CSV file
|
||||
/// \brief Reads and registers to the Stock Area and Waypoint lists
|
||||
/// from CSV files
|
||||
/**
|
||||
* CSV format is:
|
||||
* CSV format for areas is:
|
||||
* Building name;Room name;X1;Y1;Z1;X2;Y2;Z2
|
||||
*
|
||||
* CSV format for waypoints is:
|
||||
* X;Y;Z;Building name #1[;Building name #2[…[;Building name #n]]]
|
||||
*/
|
||||
class TopologyReaderCSV
|
||||
{
|
||||
protected:
|
||||
CSVFileReader file ;
|
||||
CSVFileReader areas_file ;
|
||||
CSVFileReader waypoints_file ;
|
||||
|
||||
void read_topology(void) ;
|
||||
void process_line(void) ;
|
||||
Point3D read_point(void) ;
|
||||
void process_area_line(void) ;
|
||||
void process_waypoint_line(void) ;
|
||||
Point3D read_point(CSVFileReader &file) ;
|
||||
|
||||
public:
|
||||
TopologyReaderCSV(const std::string &filename) ;
|
||||
TopologyReaderCSV(const std::string &areas_file_name,
|
||||
const std::string &waypoints_file_name) ;
|
||||
|
||||
~TopologyReaderCSV(void) {}
|
||||
} ;
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
#include "waypoint.hh"
|
||||
#include "building.hh"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace std ;
|
||||
using std::tr1::unordered_set ;
|
||||
|
||||
|
||||
|
||||
|
@ -20,7 +23,7 @@ Waypoint::Waypoint(const Building *_b,
|
|||
): Point3D(_x, _y, _z)
|
||||
{
|
||||
if (_b != NULL)
|
||||
buildings.push_back(const_cast<Building*>(_b)) ;
|
||||
buildings.insert(const_cast<Building*>(_b)) ;
|
||||
}
|
||||
|
||||
|
||||
|
@ -32,7 +35,7 @@ Waypoint::Waypoint(const Building *_b,
|
|||
Waypoint::Waypoint(const Building *_b, const Point3D &p): Point3D(p)
|
||||
{
|
||||
if (_b != NULL)
|
||||
buildings.push_back(const_cast<Building*>(_b)) ;
|
||||
buildings.insert(const_cast<Building*>(_b)) ;
|
||||
}
|
||||
|
||||
|
||||
|
@ -73,6 +76,19 @@ bool Waypoint::operator==(const Waypoint &wp) const
|
|||
}
|
||||
|
||||
|
||||
Waypoint::operator string() const
|
||||
{
|
||||
ostringstream csv ;
|
||||
csv << (Point3D) *this ;
|
||||
|
||||
for (unordered_set<Building*>::const_iterator i = buildings.begin() ;
|
||||
i != buildings.end() ; ++i)
|
||||
csv << ';' << (*i)->get_name() ;
|
||||
|
||||
return csv.str() ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ostream &operator<<(ostream &os, const Waypoint &wp)
|
||||
{
|
||||
|
@ -83,9 +99,9 @@ ostream &operator<<(ostream &os, const Waypoint &wp)
|
|||
if (wp.buildings.empty())
|
||||
os << '\n' << "Belongs to no building!" ;
|
||||
else
|
||||
for (vector<Building*>::const_iterator i = wp.buildings.begin() ;
|
||||
i != wp.buildings.end() ; ++i)
|
||||
os << '\n' << *i ;
|
||||
for (unordered_set<Building*>::const_iterator i =
|
||||
wp.buildings.begin() ; i != wp.buildings.end() ; ++i)
|
||||
os << '\n' << **i ;
|
||||
|
||||
return os ;
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@ class Building ;
|
|||
|
||||
#include "point3d.hh"
|
||||
|
||||
#include <boost/tr1/unordered_set.hpp>
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
/// Represents a junction point between several rooms (i.e. Area)
|
||||
|
@ -20,7 +20,7 @@ class Waypoint: public Point3D
|
|||
{
|
||||
protected:
|
||||
/// List of Building associated with the Waypoint
|
||||
std::vector<Building*> buildings ;
|
||||
std::tr1::unordered_set<Building*> buildings ;
|
||||
|
||||
public:
|
||||
Waypoint(const Building *_b = NULL, const float &_x = 0,
|
||||
|
@ -38,13 +38,17 @@ public:
|
|||
//@{
|
||||
/// #buildings's first element read accessor
|
||||
Building* get_1st_building(void) const ;
|
||||
const std::vector<Building*>& get_buildings(void) const ;
|
||||
const std::tr1::unordered_set<Building*>& get_buildings(void) const ;
|
||||
//@}
|
||||
|
||||
/** @name Write accessors */
|
||||
//@{
|
||||
/// Adds a Building to the \link #buildings building list\endlink
|
||||
void add_building(const Building *_b) ;
|
||||
/// Adds the Building list of \em source to #buildings
|
||||
void add_buildings(const Waypoint &source) ;
|
||||
/// Remove a Building from #buildings
|
||||
void remove_building(const Building *_b) ;
|
||||
//@}
|
||||
|
||||
/** @name Operators */
|
||||
|
@ -52,6 +56,7 @@ public:
|
|||
const Waypoint& operator=(const Waypoint &wp) ;
|
||||
bool operator==(const Waypoint &wp) const ;
|
||||
bool operator!=(const Waypoint &wp) const ;
|
||||
operator std::string(void) const ;
|
||||
//@}
|
||||
|
||||
/// Displays a Waypoint
|
||||
|
@ -70,18 +75,14 @@ public:
|
|||
*/
|
||||
inline Building* Waypoint::get_1st_building() const
|
||||
{
|
||||
try
|
||||
{
|
||||
return buildings.at(0) ;
|
||||
}
|
||||
catch (std::out_of_range &e)
|
||||
{
|
||||
return NULL ;
|
||||
}
|
||||
if (buildings.empty())
|
||||
return NULL ;
|
||||
return *buildings.begin() ;
|
||||
}
|
||||
|
||||
|
||||
inline const std::vector<Building*>& Waypoint::get_buildings() const
|
||||
inline const std::tr1::unordered_set<Building*>&
|
||||
Waypoint::get_buildings() const
|
||||
{
|
||||
return buildings ;
|
||||
}
|
||||
|
@ -101,7 +102,20 @@ inline const std::vector<Building*>& Waypoint::get_buildings() const
|
|||
inline void Waypoint::add_building(const Building *_b)
|
||||
{
|
||||
if (_b != NULL)
|
||||
buildings.push_back(const_cast<Building*>(_b)) ;
|
||||
buildings.insert(const_cast<Building*>(_b)) ;
|
||||
}
|
||||
|
||||
|
||||
inline void Waypoint::remove_building(const Building *_b)
|
||||
{
|
||||
if (_b != NULL)
|
||||
buildings.erase(const_cast<Building*>(_b)) ;
|
||||
}
|
||||
|
||||
|
||||
inline void Waypoint::add_buildings(const Waypoint &source)
|
||||
{
|
||||
buildings.insert(source.buildings.begin(), source.buildings.end()) ;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -38,12 +38,14 @@ public:
|
|||
b2.set_name("My Second Building") ;
|
||||
TS_ASSERT_EQUALS(b2.get_name(), "My Second Building") ;
|
||||
|
||||
Waypoint *wp1 = new Waypoint(&b2, 43, 45, 909) ;
|
||||
Waypoint *wp2 = new Waypoint(&b2, 12, 78, 2) ;
|
||||
b2.add_waypoint(wp1) ;
|
||||
b2.add_waypoint(wp2) ;
|
||||
waypoints1.insert(wp1) ;
|
||||
waypoints1.insert(wp2) ;
|
||||
const Waypoint &wp1 =
|
||||
Stock::find_create_waypoint(Waypoint(&b2, 43,45,909)) ;
|
||||
const Waypoint &wp2 =
|
||||
Stock::find_create_waypoint(Waypoint(&b2, 12,78,2)) ;
|
||||
b2.add_waypoint(&wp1) ;
|
||||
b2.add_waypoint(&wp2) ;
|
||||
waypoints1.insert(const_cast<Waypoint*>(&wp1)) ;
|
||||
waypoints1.insert(const_cast<Waypoint*>(&wp2)) ;
|
||||
TS_ASSERT_EQUALS(b2.get_waypoints(), waypoints1) ;
|
||||
|
||||
Area *a1 = new Area(&b2, "area1") ;
|
||||
|
@ -53,6 +55,8 @@ public:
|
|||
areas1["area1"] = a1 ;
|
||||
areas1["area2"] = a2 ;
|
||||
TS_ASSERT_EQUALS(b2.get_areas(), areas1) ;
|
||||
|
||||
// TODO: test deletion of waypoints from Stock after deletion of b2
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,6 +34,21 @@ public:
|
|||
element_not_found) ;
|
||||
}
|
||||
|
||||
void test_waypoints(void)
|
||||
{
|
||||
Point3D coordinates(42,21,98) ;
|
||||
const Building &building = Stock::find_create_building("Build") ;
|
||||
Waypoint wp1(&building, coordinates) ;
|
||||
const Waypoint
|
||||
&wp1_ref1 = Stock::find_create_waypoint(wp1),
|
||||
&wp1_ref2 = Stock::find_create_waypoint(coordinates) ;
|
||||
TS_ASSERT_EQUALS(&wp1_ref1, &wp1_ref2) ;
|
||||
|
||||
Stock::waypoint_remove_building(wp1_ref1, &building) ;
|
||||
// TODO: test if the waypoint was removed (needs a function
|
||||
// Stock::get_waypoint()).
|
||||
}
|
||||
|
||||
void test_mobiles(void)
|
||||
{
|
||||
TS_ASSERT_THROWS(Stock::get_mobile("aa:bb:cc:dd:ee:ff"),
|
||||
|
|
|
@ -5,30 +5,47 @@
|
|||
class TopologyReaderCSV_test: public CxxTest::TestSuite
|
||||
{
|
||||
private:
|
||||
std::string topology_file_name ;
|
||||
std::string areas_file_name ;
|
||||
std::string waypoints_file_name ;
|
||||
|
||||
public:
|
||||
|
||||
TopologyReaderCSV_test(void):
|
||||
topology_file_name("/tmp/TopologyReaderCSV_topology_file.csv")
|
||||
areas_file_name("/tmp/TopologyReaderCSV_areas_file.csv"),
|
||||
waypoints_file_name("/tmp/TopologyReaderCSV_waypoints_file.csv")
|
||||
{
|
||||
Stock::clear() ;
|
||||
|
||||
std::ofstream topology_file(topology_file_name.c_str()) ;
|
||||
topology_file
|
||||
std::ofstream areas_file(areas_file_name.c_str()) ;
|
||||
areas_file
|
||||
<< "My building;My room #1;1;2;3;9;8;7\n"
|
||||
<< "My building;Room #2;4;5;6;6;5;4\n"
|
||||
<< "Building #2;My room #1;1;2;3;9;8;7\n"
|
||||
<< "My building;Room #2;4;5;6;6;5;4\n"
|
||||
<< "My building;Room #2;4;5;6;6;5;4\n" ;
|
||||
topology_file.close() ;
|
||||
areas_file.close() ;
|
||||
|
||||
std::ofstream waypoints_file(waypoints_file_name.c_str()) ;
|
||||
waypoints_file
|
||||
<< "1;2;3;My building\n"
|
||||
<< "4;5;6;My building\n"
|
||||
<< "1;2;3;Building #2\n"
|
||||
<< "4;5;6;My building\n"
|
||||
<< "9;8;7;Building #2;My building\n"
|
||||
<< "4;5;6;My building\n" ;
|
||||
waypoints_file.close() ;
|
||||
|
||||
TS_ASSERT_THROWS_NOTHING(
|
||||
TopologyReaderCSV toporeader(areas_file_name,
|
||||
waypoints_file_name)) ;
|
||||
}
|
||||
|
||||
|
||||
~TopologyReaderCSV_test(void)
|
||||
{
|
||||
Stock::clear() ;
|
||||
TestUtil::remove_file(topology_file_name) ;
|
||||
TestUtil::remove_file(areas_file_name) ;
|
||||
TestUtil::remove_file(waypoints_file_name) ;
|
||||
}
|
||||
|
||||
|
||||
|
@ -44,11 +61,8 @@ public:
|
|||
}
|
||||
|
||||
|
||||
void test_topologyreadercsv(void)
|
||||
void test_areas(void)
|
||||
{
|
||||
TS_ASSERT_THROWS_NOTHING(
|
||||
TopologyReaderCSV toporeader(topology_file_name)) ;
|
||||
|
||||
Building *building1 ;
|
||||
TS_ASSERT_THROWS_NOTHING(
|
||||
building1 = const_cast<Building*>(
|
||||
|
@ -80,4 +94,54 @@ public:
|
|||
TS_ASSERT_EQUALS(*area_ptr, area1) ;
|
||||
}
|
||||
|
||||
|
||||
void test_waypoints(void)
|
||||
{
|
||||
Building *building1 ;
|
||||
TS_ASSERT_THROWS_NOTHING(
|
||||
building1 = const_cast<Building*>(
|
||||
&Stock::get_building("My building"))) ;
|
||||
Building *building2 ;
|
||||
TS_ASSERT_THROWS_NOTHING(
|
||||
building2 = const_cast<Building*>(
|
||||
&Stock::get_building("Building #2"))) ;
|
||||
|
||||
Waypoint *w, *waypoint_ptr ;
|
||||
|
||||
TS_ASSERT_EQUALS(building1->get_waypoints().size(), 3u) ;
|
||||
|
||||
const Waypoint &waypoint1 =
|
||||
Stock::find_create_waypoint(Waypoint(building1, 1,2,3)) ;
|
||||
w = const_cast<Waypoint*>(&waypoint1) ;
|
||||
|
||||
TS_ASSERT(building1->get_waypoints().find(w) !=
|
||||
building1->get_waypoints().end()) ;
|
||||
waypoint_ptr = *building1->get_waypoints().find(
|
||||
const_cast<Waypoint*>(&waypoint1)) ;
|
||||
TS_ASSERT_EQUALS(waypoint_ptr, w) ;
|
||||
|
||||
const Waypoint &waypoint2 =
|
||||
Stock::find_create_waypoint(Waypoint(building1, 4,5,6)) ;
|
||||
w = const_cast<Waypoint*>(&waypoint2) ;
|
||||
|
||||
TS_ASSERT(building1->get_waypoints().find(w) !=
|
||||
building1->get_waypoints().end()) ;
|
||||
waypoint_ptr = *building1->get_waypoints().find(
|
||||
const_cast<Waypoint*>(&waypoint2)) ;
|
||||
TS_ASSERT_EQUALS(waypoint_ptr, w) ;
|
||||
|
||||
|
||||
TS_ASSERT_EQUALS(building2->get_waypoints().size(), 2u) ;
|
||||
|
||||
const Waypoint &waypoint3 =
|
||||
Stock::find_create_waypoint(Waypoint(building2, 1,2,3)) ;
|
||||
w = const_cast<Waypoint*>(&waypoint3) ;
|
||||
|
||||
TS_ASSERT(building2->get_waypoints().find(w) !=
|
||||
building2->get_waypoints().end()) ;
|
||||
waypoint_ptr = *building2->get_waypoints().find(
|
||||
const_cast<Waypoint*>(&waypoint3)) ;
|
||||
TS_ASSERT_EQUALS(waypoint_ptr, w) ;
|
||||
}
|
||||
|
||||
} ;
|
||||
|
|
|
@ -47,10 +47,10 @@ public:
|
|||
// Write & read accessors
|
||||
Building b2("My Second Building") ;
|
||||
wp1.add_building(&b2) ;
|
||||
std::vector<Building*> vb1 ;
|
||||
vb1.push_back(&b1) ;
|
||||
vb1.push_back(&b2) ;
|
||||
TS_ASSERT_EQUALS(wp1.get_buildings(), vb1) ;
|
||||
std::tr1::unordered_set<Building*> buildings ;
|
||||
buildings.insert(&b1) ;
|
||||
buildings.insert(&b2) ;
|
||||
TS_ASSERT_EQUALS(wp1.get_buildings(), buildings) ;
|
||||
wp1.set_x(42) ;
|
||||
TS_ASSERT_EQUALS(wp1.get_x(), 42) ;
|
||||
wp1.set_y(321) ;
|
||||
|
|
Loading…
Reference in New Issue