owlps/owlps-positioning/src/referencepoint.cc

190 lines
4.5 KiB
C++

#include "referencepoint.hh"
#include "measurement.hh"
#include "calibrationrequest.hh"
#include "stock.hh"
using namespace std ;
using std::tr1::unordered_map ;
/* *** Constructors *** */
/**
* Clears #requests, but does not deallocate the values pointed by
* the elements into it.
*/
ReferencePoint::~ReferencePoint()
{
requests.clear() ;
}
/* *** Accessors *** */
map<string, Measurement> ReferencePoint::
get_all_measurements_sorted() const
{
map<string, Measurement> all ;
for (vector<CalibrationRequest*>::const_iterator i = requests.begin() ;
i != requests.end() ; ++i)
{
unordered_map<string, Measurement> measurements =
(*i)->get_measurements() ;
for (unordered_map<string, Measurement>::const_iterator j =
measurements.begin() ; j != measurements.end() ; ++j)
if (! all.insert(*j).second)
all[j->first].merge(j->second) ;
}
return all ;
}
/* *** Operations *** */
float ReferencePoint::ss_square_distance(const Request &source) const
{
assert(! requests.empty()) ;
const unordered_map<string, Measurement> &request_measurements =
source.get_measurements() ;
map<string, Measurement> request_measurements_sorted(
request_measurements.begin(),
request_measurements.end()) ;
map<string, Measurement> all_measurements_sorted =
get_all_measurements_sorted() ;
complete_with_dummy_measurements(all_measurements_sorted,
request_measurements_sorted) ;
return compute_ss_square_distance(all_measurements_sorted,
request_measurements_sorted) ;
}
/**
* APs that have not captured a Request must not have too much weight in
* the computation. Thus, in the measurements lists we compare, we add
* missing APs with a very low SS value.
* Both lists can be completed, depending of the APs they contain.
*/
void ReferencePoint::complete_with_dummy_measurements(
map<string, Measurement> &measurements1,
map<string, Measurement> &measurements2) const
{
assert(! measurements1.empty()) ;
assert(! measurements2.empty()) ;
Measurement dummy ;
dummy.add_ss(-98) ; // FIXME: should be the smallest possible value
for (map<string, Measurement>::const_iterator i =
measurements1.begin() ; i != measurements1.end() ; ++i)
if (measurements2.find(i->first) == measurements2.end())
{
dummy.set_ap(&Stock::get_ap(i->first)) ;
measurements2[i->first] = dummy ;
}
for (map<string, Measurement>::const_iterator i =
measurements2.begin() ; i != measurements2.end() ; ++i)
if (measurements1.find(i->first) == measurements1.end())
{
dummy.set_ap(&Stock::get_ap(i->first)) ;
measurements1[i->first] = dummy ;
}
}
/**
* Both lists must have the same size: you should call
* complete_with_dummy_measurements() before
* compute_ss_square_distance().
*/
float ReferencePoint::compute_ss_square_distance(
map<string, Measurement> &measurements1,
map<string, Measurement> &measurements2) const
{
assert(measurements1.size() == measurements2.size()) ;
float distance = 0 ;
for (map<string, Measurement>::const_iterator i1 =
measurements1.begin() ; i1 != measurements1.end() ; ++i1)
{
map<string, Measurement>::const_iterator i2 =
measurements2.find(i1->first) ;
assert(i2 != measurements2.end()) ;
distance += i1->second.ss_square_distance(
i2->second) ;
}
return distance ;
}
/* *** Operators *** */
const ReferencePoint& ReferencePoint::operator=(const ReferencePoint &source)
{
if (this == &source)
return *this ;
this->Point3D::operator=(source) ;
requests = source.requests ;
return *this ;
}
bool ReferencePoint::operator==(const ReferencePoint &source) const
{
if (this == &source)
return true ;
return
this->Point3D::operator==(source) &&
requests == source.requests ;
}
ostream &operator<<(ostream &os, const ReferencePoint &rp)
{
// Coordinates
os << (Point3D) rp << '\n' ;
// List of requests
if (rp.requests.empty())
os << "No request." << '\n' ;
else
for (vector<CalibrationRequest*>::const_iterator
i = rp.requests.begin() ;
i != rp.requests.end() ; ++i)
os << '\n' << **i ;
return os ;
}
/**
* This is a simple call to hash_value(Point3D), because we do not want
* to take care of the CalibrationRequest list to hash the
* ReferencePoint.
*/
size_t hash_value(const ReferencePoint &source)
{
return hash_value(static_cast<Point3D>(source)) ;
}