00001
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <wx/wx.h>
00035 #include <wx/image.h>
00036 #include <wx/splash.h>
00037 #include <wx/ffile.h>
00038 #include <wx/numdlg.h>
00039 #include <igraph/igraph.h>
00040 #include <iostream>
00041 #include <vector>
00042 #include <algorithm>
00043
00044 #include "sim_sensory.h"
00045 #include "sim_sensory_field.h"
00046 #include "sim_phenomena.h"
00047 #include "AboutDialog.h"
00048 #include "SenseDialog.h"
00049
00050 #include "icon.xpm"
00051 #include "splash.xpm"
00052
00053 #define AXIS_MIN 10
00054 #define AXIS_MAX 1000000
00055 #define AXIS_DEFAULT 1000
00056
00057
00058 IMPLEMENT_APP(SimSensory)
00059
00060
00061 SimSensory::SimSensory()
00062 {
00063 splash = true;
00064 wxHandleFatalExceptions();
00065 }
00066
00067
00068 bool SimSensory::OnInit()
00069 {
00070 if (wxApp::OnInit() == false)
00071 return false;
00072
00073 logger = new wxLogStream::wxLogStream(&std::cerr);
00074 wxLog::SetActiveTarget(logger);
00075 wxLogDebug(_("Debugging output activated."));
00076
00077 wxInitAllImageHandlers();
00078 SimSensoryExtra* frame = new SimSensoryExtra(NULL, wxID_ANY, wxEmptyString);
00079 frame->SetIcon(wxIcon(icon_xpm));
00080 SetTopWindow(frame);
00081
00082 if (splash) {
00083 new wxSplashScreen(wxBitmap(splash_xpm),
00084 wxSPLASH_CENTRE_ON_PARENT|wxSPLASH_TIMEOUT,
00085 2000, frame, wxID_ANY);
00086 wxYieldIfNeeded();
00087 }
00088
00089 frame->Show();
00090 return true;
00091 }
00092
00093
00094 void SimSensory::OnInitCmdLine(wxCmdLineParser& parser)
00095 {
00096 const wxCmdLineEntryDesc command_line_descriptor[] =
00097 {
00098 #if 0
00099 { wxCMD_LINE_SWITCH, wxT("h"), wxT("help"),
00100 _("display (optional) command line parameters"),
00101 wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
00102 #endif
00103 { wxCMD_LINE_NONE }
00104 };
00105
00106 parser.SetDesc(command_line_descriptor);
00107 parser.SetSwitchChars(wxT("-"));
00108 }
00109
00110
00111 bool SimSensory::OnCmdLineParsed(wxCmdLineParser& parser)
00112 {
00113 if (parser.GetParamCount() > 0) {
00114 parser.Usage();
00115 return false;
00116 }
00117 return true;
00118 }
00119
00120
00121 void SimSensory::OnFatalException()
00122 {
00123 GenerateReport(wxDebugReport::Context_Exception);
00124 }
00125
00126
00127 void SimSensory::GenerateReport(wxDebugReport::Context ctx)
00128 {
00129 wxDebugReportCompress *report = new wxDebugReportCompress;
00130 report->AddAll(ctx);
00131
00132 wxFileName fn(report->GetDirectory(), _T("timestamp.dbg"));
00133 wxFFile file(fn.GetFullPath(), _T("w"));
00134 if (file.IsOpened()) {
00135 wxDateTime dt = wxDateTime::Now();
00136 file.Write(dt.FormatISODate() + _T(' ') + dt.FormatISOTime());
00137 file.Close();
00138 }
00139 report->AddFile(fn.GetFullName(), _("timestamp of this report"));
00140
00141
00142 #ifndef __WXDEBUG__
00143 if (wxDebugReportPreviewStd().Show(*report)) {
00144 #endif
00145 if (report->Process()) {
00146 wxLogMessage(_("Fatal Exception: report generated in \"%s\"."),
00147 report->GetCompressedFileName().c_str());
00148 #ifdef __WXDEBUG__
00149
00150
00151
00152
00153
00154
00155 #endif
00156 report->Reset();
00157 }
00158 #ifndef __WXDEBUG__
00159 }
00160 #endif
00161 delete report;
00162 }
00163
00164
00166
00167
00168 SimSensoryExtra::SimSensoryExtra(wxWindow* parent, int id, const wxString& title,
00169 const wxPoint& pos, const wxSize& size, long style) :
00170 SimSensoryFrame(parent, id, title, pos, size, style)
00171 {
00172 const unsigned int accel_tbl_size = 5;
00173 wxAcceleratorEntry accel_entries[accel_tbl_size];
00174 accel_entries[0].Set(wxACCEL_CTRL, (int)'N', wxID_NEW);
00175 accel_entries[1].Set(wxACCEL_CTRL, (int)'O', wxID_OPEN);
00176 accel_entries[2].Set(wxACCEL_CTRL, (int)'S', wxID_SAVE);
00177 accel_entries[3].Set(wxACCEL_CTRL, (int)'W', wxID_SAVEAS);
00178 accel_entries[4].Set(wxACCEL_CTRL, (int)'Q', wxID_EXIT);
00179 wxAcceleratorTable accel_tbl(accel_tbl_size, accel_entries);
00180 SetAcceleratorTable(accel_tbl);
00181
00182 _file_name = NULL;
00183 _x_axis = AXIS_DEFAULT;
00184 _y_axis = AXIS_DEFAULT;
00185 _phenom = NONE;
00186 _on_path = false;
00187 _saved = true;
00188 }
00189
00190
00191 void SimSensoryExtra::onNew(wxCommandEvent& WXUNUSED(event))
00192 {
00193 data.clear();
00194 _phenom = NONE;
00195 _on_path = false;
00196 statusbar->SetStatusText(wxString(phenoms[_phenom], wxConvUTF8), 3);
00197 drop_field->refresh();
00198 }
00199
00200
00201 void SimSensoryExtra::onOpen(wxCommandEvent& WXUNUSED(event))
00202 {
00203 wxString prev_dir = wxT("");
00204 wxString prev_name = wxT("");
00205 if (_file_name != NULL && _file_name->IsOk()) {
00206 prev_dir = _file_name->GetPath();
00207 prev_name = _file_name->GetFullName();
00208 }
00209
00210 wxFileDialog dialog(this,
00211 _("Open a new sensory data file"), prev_dir,
00212 prev_name, _T("Sensory data file|*.phenom"), wxOPEN);
00213 if (dialog.ShowModal() == wxID_OK) {
00214 wxFFile data_file;
00215 if (_file_name != NULL && _file_name->IsOk()) {
00216 delete _file_name;
00217 _file_name = NULL;
00218 }
00219 _file_name = new wxFileName(dialog.GetDirectory(), dialog.GetFilename());
00220
00221 if (!data_file.Open(_file_name->GetFullPath(), wxT("r"))) {
00222 wxLogError(_("Unable to open ") + _file_name->GetFullPath());
00223 return;
00224 }
00225 if (read_scenario(data_file.fp(), data) < 0) {
00226 wxLogError(_("Unable to read ") + _file_name->GetFullPath());
00227 }
00228 data_file.Close();
00229 drop_field->refresh();
00230 }
00231 }
00232
00233
00234 void SimSensoryExtra::onSave(wxCommandEvent& WXUNUSED(event))
00235 {
00236 wxFFile data_file;
00237 if (_file_name != NULL && _file_name->IsOk()) {
00238 if (!data_file.Open(_file_name->GetFullPath(), wxT("w"))) {
00239 wxLogError(_("Unable to save to ") + _file_name->GetFullPath());
00240 return;
00241 }
00242 for (int i = 0; i < data.size(); i++) {
00243 data_file.Write(wxString(data[i].toString(), wxConvUTF8));
00244 }
00245 data_file.Close();
00246 _saved = true;
00247 }
00248 }
00249
00250
00251 void SimSensoryExtra::onSaveAs(wxCommandEvent& event)
00252 {
00253 wxString prev_dir = wxT("");
00254 if (_file_name !=NULL && _file_name->IsOk())
00255 prev_dir = _file_name->GetPath();
00256
00257 wxFileDialog dialog(this,
00258 _("Save sensory data file as"), prev_dir, wxT(""),
00259 _T("Sensory data file|*.phenom"), wxSAVE);
00260 if (dialog.ShowModal() == wxID_OK) {
00261 if (_file_name != NULL && _file_name->IsOk()) {
00262 delete _file_name;
00263 _file_name = NULL;
00264 }
00265 _file_name = new wxFileName(dialog.GetDirectory(), dialog.GetFilename());
00266
00267 onSave(event);
00268 }
00269 }
00270
00271
00272 void SimSensoryExtra::onCompute(wxCommandEvent& event)
00273 {
00274 if(!_saved)
00275 onSave(event);
00276
00277 wxString prev_dir = wxT("");
00278 if (_file_name !=NULL && _file_name->IsOk())
00279 prev_dir = _file_name->GetPath();
00280
00281 wxFileDialog net_dialog(this,
00282 _("Open node network graph"), prev_dir, wxT(""),
00283 _T("GML file|*.gml"), wxOPEN);
00284 if (net_dialog.ShowModal() == wxID_OK) {
00285 wxFileName net_filename(net_dialog.GetDirectory(),
00286 net_dialog.GetFilename());
00287 prev_dir = net_dialog.GetDirectory();
00288 wxLogDebug(_("Use ") + net_filename.GetFullPath() +
00289 _(" to compute adc file"));
00290
00291 wxFileDialog adc_dialog(this,
00292 _("Save ADC simulation data as..."),
00293 prev_dir, wxT(""),
00294 _T("ADC data file|*.adc"), wxSAVE);
00295 if (adc_dialog.ShowModal() == wxID_OK) {
00296 wxFileName adc_filename(adc_dialog.GetDirectory(),
00297 adc_dialog.GetFilename());
00298 wxLogDebug(_("Save as ") + adc_filename.GetFullPath());
00299
00300 if (net_filename.IsOk() && adc_filename.IsOk())
00301 compute_adc(_file_name->GetFullPath().mb_str(),
00302 net_filename.GetFullPath().mb_str(),
00303 adc_filename.GetFullPath().mb_str());
00304 }
00305 }
00306 }
00307
00308
00309 void SimSensoryExtra::onExit(wxCommandEvent& event)
00310 {
00311 onNew(event);
00312 Close();
00313 }
00314
00315
00316 void SimSensoryExtra::onAbout(wxCommandEvent& WXUNUSED(event))
00317 {
00318 AboutDialog dialog(this, wxID_ANY, _("About..."));
00319 if (dialog.ShowModal() == wxID_OK)
00320 ;
00321 }
00322
00323
00324 void SimSensoryExtra::onXAxis(wxCommandEvent& WXUNUSED(event))
00325 {
00326 _x_axis = wxGetNumberFromUser(wxEmptyString, _("Set X axis length: "),
00327 _("X axis"), _x_axis, AXIS_MIN, AXIS_MAX,
00328 this);
00329 statusbar->SetStatusText(wxString::Format(_("Size: x = %d, y = %d"),
00330 _x_axis, _y_axis), 1);
00331 drop_field->refresh();
00332 }
00333
00334
00335 void SimSensoryExtra::onYAxis(wxCommandEvent& WXUNUSED(event))
00336 {
00337 _y_axis = wxGetNumberFromUser(wxEmptyString, _("Set Y axis length: "),
00338 _("Y axis"), _y_axis, AXIS_MIN, AXIS_MAX,
00339 this);
00340 statusbar->SetStatusText(wxString::Format(_("Size: x = %d, y = %d"),
00341 _x_axis, _y_axis), 1);
00342 drop_field->refresh();
00343 }
00344
00345
00346 void SimSensoryExtra::onAmbSound(wxCommandEvent& WXUNUSED(event))
00347 {
00348 _phenom = AMBSOUND;
00349 statusbar->SetStatusText(wxString(phenoms[_phenom], wxConvUTF8), 3);
00350 _on_path = false;
00351 }
00352
00353
00354 void SimSensoryExtra::onAmbLight(wxCommandEvent& WXUNUSED(event))
00355 {
00356 _phenom = AMBLIGHT;
00357 statusbar->SetStatusText(wxString(phenoms[_phenom], wxConvUTF8), 3);
00358 _on_path = false;
00359 }
00360
00361
00362 void SimSensoryExtra::onTemp(wxCommandEvent& WXUNUSED(event))
00363 {
00364 _phenom = AMBTEMP;
00365 statusbar->SetStatusText(wxString(phenoms[_phenom], wxConvUTF8), 3);
00366 _on_path = false;
00367 }
00368
00369
00370 void SimSensoryExtra::onAmbRad(wxCommandEvent& WXUNUSED(event))
00371 {
00372 _phenom = AMBRAD;
00373 statusbar->SetStatusText(wxString(phenoms[_phenom], wxConvUTF8), 3);
00374 _on_path = false;
00375 }
00376
00377
00378 void SimSensoryExtra::onSound(wxCommandEvent& WXUNUSED(event))
00379 {
00380 _phenom = SOUND;
00381 statusbar->SetStatusText(wxString(phenoms[_phenom], wxConvUTF8), 3);
00382 _on_path = false;
00383 }
00384
00385
00386 void SimSensoryExtra::onLight(wxCommandEvent& WXUNUSED(event))
00387 {
00388 _phenom = LIGHT;
00389 statusbar->SetStatusText(wxString(phenoms[_phenom], wxConvUTF8), 3);
00390 _on_path = false;
00391 }
00392
00393
00394 void SimSensoryExtra::onAccel(wxCommandEvent& WXUNUSED(event))
00395 {
00396 _phenom = ACCEL_X;
00397 statusbar->SetStatusText(wxString(phenoms[_phenom], wxConvUTF8), 3);
00398 _on_path = false;
00399 }
00400
00401
00402 void SimSensoryExtra::onMag(wxCommandEvent& WXUNUSED(event))
00403 {
00404 _phenom = MAG_X;
00405 statusbar->SetStatusText(wxString(phenoms[_phenom], wxConvUTF8), 3);
00406 _on_path = false;
00407 }
00408
00409
00410 void SimSensoryExtra::onRad(wxCommandEvent& WXUNUSED(event))
00411 {
00412 _phenom = RAD;
00413 statusbar->SetStatusText(wxString(phenoms[_phenom], wxConvUTF8), 3);
00414 _on_path = false;
00415 }
00416
00417
00418 unsigned int SimSensoryExtra::getXAxis()
00419 {
00420 return _x_axis;
00421 }
00422
00423
00424 unsigned int SimSensoryExtra::getYAxis()
00425 {
00426 return _y_axis;
00427 }
00428
00429
00430 void SimSensoryExtra::setFieldPosition(double x, double y)
00431 {
00432 statusbar->SetStatusText(wxString::Format(_("Position: x = %d, y = %d"),
00433 _x_axis - static_cast<int>(x),
00434 static_cast<int>(y)), 0);
00435 }
00436
00437
00438 Phenom SimSensoryExtra::getCurrentPhenomType()
00439 {
00440 return _phenom;
00441 }
00442
00443
00444 void SimSensoryExtra::setSaved(bool s)
00445 {
00446 _saved = s;
00447 }
00448
00449
00450 bool SimSensoryExtra::isOnPath()
00451 {
00452 return _on_path;
00453 }
00454
00455
00456 void SimSensoryExtra::putOnPath()
00457 {
00458 _on_path = true;
00459 }
00460
00461
00463
00464
00465 void SenseDialog::onOK(wxCommandEvent& WXUNUSED(event))
00466 {
00467 EndModal(wxID_OK);
00468 }
00469
00470
00471 void SenseDialog::onCancel(wxCommandEvent& WXUNUSED(event))
00472 {
00473 EndModal(wxID_CANCEL);
00474 }
00475
00476
00478
00479
00480 SensoryField::SensoryField(wxWindow* parent, wxWindowID id) :
00481 wxPanel(parent, id)
00482 {
00483 _main = reinterpret_cast<SimSensoryExtra*>(parent);
00484 }
00485
00486
00487 BEGIN_EVENT_TABLE(SensoryField, wxPanel)
00488 EVT_PAINT(SensoryField::render)
00489 EVT_MOTION(SensoryField::onMove)
00490 EVT_LEFT_UP(SensoryField::onClick)
00491 EVT_RIGHT_DOWN(SensoryField::onCtrl)
00492 END_EVENT_TABLE()
00493
00494 #define max(x, y) (x > y ? x : y)
00495 #define min(x, y) (x < y ? x : y)
00496
00497
00498 wxPoint SensoryField::_convertMouseToCoord(wxDC &dc, int x, int y)
00499 {
00500 wxPoint coord;
00501 coord.x = dc.DeviceToLogicalX(x);
00502 coord.y = dc.DeviceToLogicalY(y);
00503 return coord;
00504 }
00505
00506
00507 wxPoint SensoryField::_convertMouseToCoord(wxDC &dc, wxPoint &mouse)
00508 {
00509 return _convertMouseToCoord(dc, mouse.x, mouse.y);
00510 }
00511
00512
00513 void SensoryField::_paintField(wxDC &dc)
00514 {
00515 dc.Clear();
00516 _prepDevice(dc);
00517 int x_len = static_cast<int>(_main->getXAxis() / 1000.0);
00518 int y_len = static_cast<int>(_main->getYAxis() / 1000.0);
00519 int len = min(x_len, y_len);
00520
00521 for (int i = 0; i < _main->data.size(); i++) {
00522 SensorData d = _main->data[i];
00523 wxString color(d.source->getColor(), wxConvUTF8);
00524 dc.SetPen(*wxTRANSPARENT_PEN);
00525 dc.SetBrush(wxBrush(color, wxSOLID));
00526
00527 if (d.source->isAmbient()) {
00528 wxPoint corner;
00529 wxSize size;
00530 AmbientPhenomenon *amb = reinterpret_cast<AmbientPhenomenon*>(d.source);
00531 size.Set(static_cast<int>(x_len * 8.0), static_cast<int>(y_len * 8.0));
00532 corner.x = d.x - static_cast<int>(size.GetWidth() / 2.0);
00533 corner.y = d.y - static_cast<int>(size.GetHeight() / 2.0);
00534 dc.DrawEllipse(corner, size);
00535
00536 switch (d.source->getType()) {
00537 case AMBSOUND:
00538 dc.SetBrush(wxBrush(color, wxVERTICAL_HATCH));
00539 break;
00540 case AMBLIGHT:
00541 dc.SetBrush(wxBrush(color, wxHORIZONTAL_HATCH));
00542 break;
00543 case AMBTEMP:
00544 dc.SetBrush(wxBrush(color, wxBDIAGONAL_HATCH));
00545 break;
00546 case AMBRAD:
00547 dc.SetBrush(wxBrush(color, wxFDIAGONAL_HATCH));
00548 break;
00549 }
00550 size.Set(x_len * amb->getRange(), y_len * amb->getRange());
00551 corner.x = d.x - static_cast<int>(size.GetWidth() / 2.0);
00552 corner.y = d.y - static_cast<int>(size.GetHeight() / 2.0);
00553 int saved = dc.GetLogicalFunction();
00554 dc.SetLogicalFunction(wxAND);
00555 dc.DrawEllipse(corner, size);
00556 dc.SetLogicalFunction(saved);
00557 }
00558 else {
00559 wxPoint corner;
00560 wxSize size;
00561 double x_size = max((x_len * 20.0), 2.0);
00562 double y_size = max((y_len * 20.0), 2.0);
00563 size.Set(static_cast<int>(x_size), static_cast<int>(y_size));
00564 corner.x = d.x - static_cast<int>(x_size / 2.0);
00565 corner.y = d.y - static_cast<int>(y_size / 2.0);
00566 dc.DrawEllipse(corner, size);
00567 if (d.prev != NULL) {
00568 dc.SetPen(wxPen(wxT("black"), len, wxSOLID));
00569 dc.DrawLine(d.x, d.y, d.prev->x, d.prev->y);
00570 }
00571 }
00572 }
00573 }
00574
00575
00576 void SensoryField::_prepDevice(wxDC &dc)
00577 {
00578 double win_x = GetSize().GetWidth();
00579 double win_y = GetSize().GetHeight();
00580 dc.SetAxisOrientation(true, true);
00581 dc.SetUserScale((win_x / _main->getXAxis()), (win_y / _main->getYAxis()));
00582 dc.SetLogicalOrigin(0, -_main->getYAxis());
00583 dc.SetMapMode(wxMM_TEXT);
00584 }
00585
00586
00587 void SensoryField::render(wxPaintEvent& WXUNUSED(event))
00588 {
00589 refresh();
00590 }
00591
00592
00593 void SensoryField::refresh()
00594 {
00595 wxPaintDC dc(this);
00596 _paintField(dc);
00597 }
00598
00599
00600 void SensoryField::onMove(wxMouseEvent& event)
00601 {
00602 wxClientDC dc(this);
00603 _prepDevice(dc);
00604 wxPoint coord = _convertMouseToCoord(dc, event.m_x, event.m_y);
00605 coord.x = _main->getXAxis() - coord.x;
00606 _main->setFieldPosition(coord.x, coord.y);
00607 }
00608
00609
00610 void SensoryField::onClick(wxMouseEvent& event)
00611 {
00612 Phenom p = _main->getCurrentPhenomType();
00613 if (p != NONE) {
00614 wxClientDC dc(this);
00615 _prepDevice(dc);
00616 wxPoint coord = _convertMouseToCoord(dc, event.m_x, event.m_y);
00617 wxLogDebug(_("Add ") + wxString(phenoms[p], wxConvUTF8) +
00618 wxString::Format(_(" at %d, %d"), coord.x, coord.y));
00619 if (_main->isOnPath()) {
00620 SensorData *d = new SensorData(p, coord.x, coord.y,
00621 &_main->data.back());
00622 d->on_path = true;
00623 _main->data.push_back(*d);
00624 }
00625 else {
00626 SensorData *d = new SensorData(p, coord.x, coord.y);
00627 _main->data.push_back(*d);
00628 _main->putOnPath();
00629 }
00630 _paintField(dc);
00631 _main->setSaved(false);
00632 }
00633 }
00634
00635
00636 void SensoryField::onCtrl(wxMouseEvent& event)
00637 {
00638 wxClientDC dc(this);
00639 _prepDevice(dc);
00640 wxPoint coord = _convertMouseToCoord(dc, event.m_x, event.m_y);
00641
00642 SensorData compare(NONE, coord.x, coord.y);
00643 std::vector<SensorData>::iterator result;
00644 result = std::find(_main->data.begin(), _main->data.end(), compare);
00645 if (result == _main->data.end())
00646 return;
00647 SensorData datum = *result;
00648
00649 wxLogDebug(_("Modify ")+ wxString(datum.source->toString(), wxConvUTF8) +
00650 wxString::Format(_(" at %d, %d"), coord.x, coord.y));
00651
00652 SenseDialog dialog(this, wxID_ANY, _("Modify sensory details"));
00653 dialog.SetPhenomenon(wxString(datum.source->toString(), wxConvUTF8));
00654 if (datum.on_path) {
00655 if (datum.prev != NULL)
00656 dialog.SetStrength(datum.prev->strength);
00657 dialog.TimeOff();
00658 dialog.SpeedOff();
00659 dialog.AccelOff();
00660 }
00661 else {
00662 dialog.DisableSpeed();
00663 dialog.DisableAccel();
00664 dialog.TimeOn();
00665 }
00666
00667 if (dialog.ShowModal() == wxID_OK) {
00668 long accel = -1;
00669 long speed = -1;
00670
00671 datum.strength = dialog.GetStrength();
00672 datum.source->setRate(dialog.GetRate());
00673
00674 if (dialog.IsTime()) {
00675 long long t = dialog.GetTime();
00676 if (t > 0) {
00677 datum.time = t;
00678 if (datum.on_path && datum.prev)
00679 datum.speed = datum.distanceTo(*datum.prev) / (t - datum.prev->time);
00680 else
00681 datum.speed = 0;
00682 }
00683 }
00684 else if (dialog.IsSpeed()) {
00685 long s = dialog.GetSpeed();
00686 if (s > 0 ) {
00687 datum.speed = s;
00688 if (datum.on_path && datum.prev)
00689 datum.time = datum.distanceTo(*datum.prev) / s;
00690 }
00691 }
00692 else if (dialog.IsAccel()) {
00693 long a = dialog.GetAccel();
00694 if (a != 0 && datum.on_path && datum.prev) {
00695 long dist = datum.distanceTo(*datum.prev);
00696 accel = a;
00697 speed = datum.prev->speed;
00698
00699
00700
00701 datum.time = (2 * dist) /
00702 (unsigned long long)(sqrt(2 * a * dist + (speed * speed)) + speed);
00703 }
00704 }
00705
00706 if (datum.on_path && datum.prev) {
00707 SensorData *last = datum.prev;
00708 long long t_diff = datum.time - datum.prev->time;
00709 int intervals = t_diff / datum.source->getRate();
00710
00711 for (int i = 0; i < intervals; i++) {
00712 unsigned int x, y;
00713 if (accel != -1) {
00714 long long i_time = i * datum.source->getRate();
00715
00716
00717 long i_dist = ((speed * i_time) + ((accel * i_time * i_time) / 2)) /
00718 datum.distanceTo(*datum.prev);
00719 x = ((datum.x - datum.prev->x) * i_dist) + datum.prev->x;
00720 y = ((datum.y - datum.prev->y) * i_dist) + datum.prev->y;
00721 speed = speed * (accel / datum.source->getRate());
00722 }
00723 else {
00724 x = ((datum.x - datum.prev->x) * i) + datum.prev->x;
00725 y = ((datum.y - datum.prev->y) * i) + datum.prev->y;
00726 }
00727 SensorData *d = new SensorData(datum.source->getType(), x, y);
00728 d->time = datum.prev->time + (i * datum.source->getRate());
00729 d->prev = last;
00730 _main->data.push_back(*d);
00731 last = d;
00732 }
00733 }
00734 }
00735 }