00001 #include <set>
00002 #include <fstream>
00003 #include <CGAL/IO/Qt_widget.h>
00004 #include "range_obs.hpp"
00005 #include "jet.hpp"
00006
00007 using namespace Arak;
00008 using namespace Arak::Geometry;
00009
00010 #define REGISTER_QUERY_POINTS
00011
00012 ArakPosteriorRangeObs::ArakPosteriorRangeObs(const ArakProcess& prior,
00013 const Arak::Util::PropertyMap& props)
00014 : ArakProcess(prior.getColoring()), prior(prior), updateId(0), lp(0.0) {
00015 using namespace Arak::Util;
00016 assert(parse(getp(props, "arak.range_obs.max_range"), maxRange));
00017 assert(parse(getp(props, "arak.range_obs.range_var"), rangeVar));
00018 assert(parse(getp(props, "arak.range_obs.prob_outlier"), pOutlier));
00019 assert(parse(getp(props, "arak.range_obs.prob_max_range_false_pos"),
00020 pMaxFalsePos));
00021 assert(parse(getp(props, "arak.range_obs.prob_max_range_false_neg"),
00022 pMaxFalseNeg));
00023 const std::string& datafile_path =
00024 getp(props, "arak.range_obs.data_file");
00025 std::ifstream in(datafile_path.data());
00026 assert(in.good());
00027 int n;
00028 in >> n;
00029 #ifdef REGISTER_QUERY_POINTS
00030 std::vector<Geometry::Point> sources;
00031 sources.reserve(n);
00032 #endif
00033 obs.reserve(n);
00034 const Geometry::Rectangle& bd = prior.getColoring().boundary();
00035 for (int i = 0; i < n; i++) {
00036 Geometry::Point p, q;
00037 in >> p >> q;
00038
00039
00040
00041
00042
00043
00044
00045 RangeObs* o = new RangeObs(p, q, maxRange);
00046 #ifdef REGISTER_QUERY_POINTS
00047 sources.push_back(p);
00048 #endif
00049 obs.push_back(o);
00050 }
00051 assert(!in.bad());
00052
00053 int rows, cols;
00054 if (hasp(props, "arak.range_obs.rows") &&
00055 hasp(props, "arak.range_obs.cols")) {
00056 assert(parse(getp(props, "arak.range_obs.rows"), rows));
00057 assert(parse(getp(props, "arak.range_obs.cols"), cols));
00058 } else {
00059
00060
00061 const double obsPerCell = 3.0;
00062 const double numCells = double(obs.size()) / obsPerCell;
00063 const double ar =
00064 CGAL::to_double((c.boundary().xmax() - c.boundary().xmin()) /
00065 (c.boundary().ymax() - c.boundary().ymin()));
00066 rows = int(sqrt(numCells / ar));
00067 cols = int(numCells) / rows;
00068
00069 }
00070 obsIndex = new RangeObsIndex(bd, rows, cols);
00071
00072 for (std::vector<RangeObs*>::iterator it = obs.begin();
00073 it != obs.end(); it++)
00074 lp += updateObsLP(*(*it), true);
00075
00076 c.addListener(*this);
00077 #ifdef REGISTER_QUERY_POINTS
00078 QueryPointIndex index(sources, obs);
00079 c.addQueryPoints(index);
00080 #endif
00081 }
00082
00083 ArakPosteriorRangeObs::RangeObs::RangeObs(const Geometry::Point& source,
00084 const Geometry::Point& target,
00085 const double maxRange) {
00086 this->source = source;
00087 this->target = target;
00088 const Geometry::Vector v = target - source;
00089 range = sqrt(CGAL::to_double(v.squared_length()));
00090 max = source + v * (maxRange / range);
00091 isMaxRange = (range > maxRange - 1e-2);
00092 curContact = source;
00093 curRange = 0.0;
00094 lp = 0.0;
00095 updateId = 0;
00096 }
00097
00098 bool ArakPosteriorRangeObs::retraceObs(RangeObs& o, bool init) const {
00099 Coloring::IntEdgeHandle e;
00100 Geometry::Kernel::FT sd;
00101 Geometry::Point oldContact = o.curContact;
00102 if (c.trace(o.source, o.max, e, o.curContact, sd)) {
00103 o.curRange = sqrt(CGAL::to_double(sd));
00104 } else {
00105 o.curContact = o.max;
00106 o.curRange = maxRange;
00107 }
00108 if (oldContact != o.curContact) {
00109
00110 for (RangeObs::CellEntryList::iterator it = o.entries.begin();
00111 it != o.entries.end(); it++)
00112 it->remove();
00113 o.unused.splice(o.unused.begin(), o.entries,
00114 o.entries.begin(), o.entries.end());
00115
00116
00117 typedef RangeObsIndex::LineCellIterator Iterator;
00118 Iterator it, end;
00119 if (obsIndex->boundary().has_on_unbounded_side(o.curContact))
00120 it = Iterator(*obsIndex, o.source, o.curContact, Iterator::RAY());
00121 else
00122 it = Iterator(*obsIndex, o.source, o.curContact, Iterator::SEGMENT());
00123 while (it != end) {
00124
00125
00126
00127
00128
00129 RangeObsIndex::Cell::Entry entry = it->add(RangeObsHandle(o));
00130
00131
00132 if (o.unused.empty())
00133 o.entries.push_front(entry);
00134 else {
00135 RangeObs::CellEntryList::iterator jt = o.unused.begin();
00136 *jt = entry;
00137 o.entries.splice(o.entries.begin(), o.unused, jt);
00138 }
00139 ++it;
00140 }
00141 return true;
00142 } else
00143 return false;
00144 }
00145
00146 double ArakPosteriorRangeObs::updateObsLP(RangeObs& o, bool init) const {
00147
00148 o.updateId = updateId;
00149
00150 if (!retraceObs(o, init)) return 0.0;
00151
00152 const double oldLP = o.lp;
00153
00154 #ifdef REGISTER_QUERY_POINTS
00155 Color sourceColor = o.sourceColor;
00156 #else
00157 Color sourceColor = c.color(o.source);
00158 #endif
00159 if (sourceColor == BLACK) {
00160 o.lp = -1e10;
00161 } else {
00162 if (o.curRange < maxRange) {
00163
00164 if (o.isMaxRange)
00165
00166 o.lp = ln(pMaxFalsePos);
00167 else {
00168
00169 double gl = exp(-pow(o.range - o.curRange, 2) / (2.0 * rangeVar)) /
00170 sqrt(rangeVar * 2.0 * M_PI);
00171 o.lp = ln((1.0 - pMaxFalsePos) *
00172 ((pOutlier / maxRange) + (1.0 - pOutlier) * gl));
00173 }
00174
00175 } else {
00176
00177 if (o.isMaxRange)
00178
00179 o.lp = ln(1.0 - pMaxFalseNeg);
00180 else
00181
00182 o.lp = ln(pMaxFalseNeg) - ln(maxRange);
00183 }
00184 }
00185 return o.lp - oldLP;
00186 }
00187
00188 double ArakPosteriorRangeObs::logMeasure() const {
00189 return prior.logMeasure();
00190 }
00191
00192 double ArakPosteriorRangeObs::potential() const {
00193 return prior.potential() - lp;
00194 }
00195
00196 ArakPosteriorRangeObs::~ArakPosteriorRangeObs() {
00197 for (std::vector<RangeObs*>::iterator it = obs.begin();
00198 it != obs.end(); it++)
00199 delete *it;
00200 delete obsIndex;
00201 }
00202
00203 void ArakPosteriorRangeObs::visualize(CGAL::Qt_widget& widget) const {
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 for (std::vector<RangeObs*>::const_iterator it = obs.begin();
00220 it != obs.end(); it++) {
00221 const RangeObs* o = *it;
00222 const double max_likelihood = 5.0;
00223 double normalized = std::min(exp(o->lp), max_likelihood) / max_likelihood;
00224 int n = int(double(jet_size - 1) * normalized);
00225 const CGAL::Color& color = jet_colors[n];
00226
00227
00228
00229
00230
00231
00232
00233
00234 widget << color << Segment(o->source, o->target);
00235 }
00236 }
00237
00238 void ArakPosteriorRangeObs::update(const Geometry::Point& a,
00239 const Geometry::Point& b,
00240 const Geometry::Point& c) {
00241
00242
00243 Geometry::Triangle t(a, b, c);
00244 RangeObsIndex::TriangleCellIterator it(*obsIndex, t), end;
00245 do {
00246 RangeObsIndex::Cell::ItemList& obsList = it->getItemList();
00247 typedef RangeObsIndex::Cell::ItemList::iterator Iterator;
00248 Iterator jt = obsList.begin();
00249 bool done = (jt == obsList.end());
00250 while (!done) {
00251 RangeObsHandle o = *jt;
00252 done = (++jt == obsList.end());
00253 if (o->updateId != updateId)
00254 lp += updateObsLP(*o);
00255 }
00256 } while (++it != end);
00257 }
00258
00259 void ArakPosteriorRangeObs::recolored(const Geometry::Point& a,
00260 const Geometry::Point& b,
00261 const Geometry::Point& c) {
00262 updateId++;
00263 update(a, b, c);
00264 }
00265
00266 void ArakPosteriorRangeObs::recolored(const Geometry::Point& a,
00267 const Geometry::Point& b,
00268 const Geometry::Point& c,
00269 const Geometry::Point& d) {
00270 updateId++;
00271 update(a, b, c);
00272 update(a, d, c);
00273 }
00274