00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00035
00036
00037
00038 #include "Neuro/SimulationViewerEyeRegion.H"
00039
00040 #include "Component/OptionManager.H"
00041 #include "Component/ModelOptionDef.H"
00042 #include "Transport/TransportOpts.H"
00043 #include "Channels/ChannelBase.H"
00044 #include "Image/DrawOps.H"
00045 #include "Image/ColorOps.H"
00046 #include "Image/CutPaste.H"
00047 #include "Image/FilterOps.H"
00048 #include "Image/MathOps.H"
00049 #include "Image/ShapeOps.H"
00050 #include "Image/Transforms.H"
00051 #include "Neuro/NeuroOpts.H"
00052 #include "Neuro/NeuroSimEvents.H"
00053 #include "Psycho/EyeData.H"
00054 #include "Simulation/SimEventQueue.H"
00055 #include "Util/sformat.H"
00056
00057 #include "rutz/trace.h"
00058
00059 #include <fstream>
00060
00061
00062 const ModelOptionDef OPT_SimViewXMLInputFile =
00063 { MODOPT_ARG(std::string), "SimViewXMLInputFile", &MOC_INPUT, OPTEXP_CORE,
00064 "XML file to gather region data from.",
00065 "xml-file", '\0', "string", ""};
00066
00067 const ModelOptionDef OPT_SimViewSelectedObjects =
00068 { MODOPT_ARG(std::string), "SimViewSelectedObjects", &MOC_DISPLAY, OPTEXP_CORE,
00069 "Only display objects matching the given name.",
00070 "objs-filter", '\0', "string", "" };
00071
00072 const ModelOptionDef OPT_SimViewObjDrawMode =
00073 { MODOPT_ARG(std::string), "SimViewObjDrawMode", &MOC_DISPLAY, OPTEXP_CORE,
00074 "Chooses which objects are displayed. Note that these options currently "
00075 "depend upon --display-patch and --display-foa. \n"
00076 "\t'selected' objects are objects which are selected by the option --objs-filter.\n"
00077 "\t'targeted' objects are objects that saccades are directed towards.\n"
00078 "\t'traced' objects are objects that are followed by an eyetrace.\n"
00079 "\t'none' and 'all' are none and all labeled objects, respectively.",
00080 "obj-drawmode", '\0', "<none|selected|targeted|traced|all>", "all" };
00081
00082 const ModelOptionDef OPT_SimViewHighlightMode =
00083 { MODOPT_ARG(std::string), "SimViewHighlightMode", &MOC_DISPLAY, OPTEXP_CORE,
00084 "Chooses when objects are highlighted. Note that these options currently "
00085 "depend upon --display-patch and --display-foa. Also, highlighting is currently "
00086 "ambiguous with multiple eye-traces. \n"
00087 "\t'targeted' triggers highlighting only at the FOA.\n"
00088 "\t'traced' highlights the object that is at the point of gaze.",
00089 "obj-highlightmode", '\0', "<off|targeted|traced>", "targeted" };
00090
00091
00092 const ModelOptionDef OPT_SimViewPrependHeader =
00093 { MODOPT_FLAG, "SimViewPrependHeader", &MOC_DISPLAY, OPTEXP_CORE,
00094 "Determines whether to add a header to svem or region output",
00095 "prepend-header", '\0', "", "false" };
00096
00097
00098 const ModelOptionDef OPT_SimViewRegionOutFile =
00099 { MODOPT_ARG_STRING, "SimViewRegionOutFile", &MOC_DISPLAY, OPTEXP_CORE,
00100 "File name for region-based output data (or empty to not save output data).",
00101 "region-out-fname", '\0', "<file>", "" };
00102
00103
00104 SimulationViewerEyeRegion::
00105 SimulationViewerEyeRegion(OptionManager& mgr, const std::string& descrName,
00106 const std::string& tagName) :
00107 SimulationViewerEyeMvt(mgr, descrName, tagName),
00108 itsRegionOutFname(&OPT_SimViewRegionOutFile, this),
00109 itsXMLFname(&OPT_SimViewXMLInputFile, this),
00110 itsSelectedObjects(&OPT_SimViewSelectedObjects, this),
00111 itsObjectDrawMode(&OPT_SimViewObjDrawMode, this),
00112 itsHighlightMode(&OPT_SimViewHighlightMode, this),
00113 itsPrependHeader(&OPT_SimViewPrependHeader,this),
00114 itsLineThickness("SVLineThickness", this, 2),
00115 itsHitTransparency("SVHitTransparency", this, 0.65),
00116 itsRandomColoring("SVRandomColoring", this, true),
00117 itsRegionOutFile(0), itsRegions(), itsTargetsMask(), itsNumObjects(0),
00118 itsCurrRegionID(NULL_OBJ),
00119 itsObjectEntry(new EyeData(1,1,1,SACSTATE_FIX,false)),
00120 itsObjectOnset(SimTime::ZERO()), itsObjectFrameOnset(0), itsRandColors(),
00121 itsObjectsNames(), itsRegHeaderWritten(false)
00122 {
00123 GVX_TRACE(__PRETTY_FUNCTION__);
00124 }
00125
00126
00127 SimulationViewerEyeRegion::~SimulationViewerEyeRegion()
00128 {
00129 GVX_TRACE(__PRETTY_FUNCTION__);
00130 }
00131
00132
00133 void SimulationViewerEyeRegion::start1()
00134 {
00135 if (itsXMLFname.getVal().empty())
00136 LFATAL("No XML file given - use --xml-file option with sv-Type EyeRegion");
00137 else
00138 {
00139
00140 itsObjectsInfo.reset(new TestImages(itsXMLFname.getVal().c_str(),
00141 TestImages::XMLFILE));
00142
00143
00144
00145
00146 Scene thisScene;
00147 std::string nom;
00148 for (uint i = 0; i < itsObjectsInfo->getNumScenes(); i++)
00149 {
00150 thisScene = itsObjectsInfo->getSceneData(i);
00151 for (std::vector<Object>::iterator iObj = thisScene.objects.begin();
00152 iObj != thisScene.objects.end(); iObj++)
00153 {
00154
00155 if((*iObj).id >= itsNumObjects)
00156 {
00157 itsNumObjects = (*iObj).id+1;
00158 itsObjectsNames.resize(itsNumObjects,std::string());
00159 }
00160
00161
00162 nom = (*iObj).name;
00163 if(!nom.empty() && (nom[nom.length()-1] == '_'))
00164 nom.erase(nom.length()-1);
00165 if(!nom.empty() && (nom[0] == '_')) nom.erase(0,1);
00166
00167
00168 if(itsObjectsNames[(*iObj).id].empty()==true)
00169 {
00170 itsObjectsNames[(*iObj).id] = nom;
00171 LINFO("assigning obj %s to obj id #%d from frame %u",
00172 nom.c_str(),(*iObj).id,i);
00173 }
00174
00175
00176 if (itsObjectsNames[(*iObj).id].compare(nom) != 0)
00177 LFATAL("XML file %s has name conflict for object #%u, %s <-> %s",
00178 itsXMLFname.getVal().c_str(), (*iObj).id,
00179 itsObjectsNames[(*iObj).id].c_str(), nom.c_str());
00180 }
00181
00182 }
00183 }
00184
00185
00186 if (!itsRegionOutFname.getVal().empty())
00187 {
00188 if (itsRegionOutFile) delete itsRegionOutFile;
00189 itsRegionOutFile = new std::ofstream(itsRegionOutFname.getVal().c_str());
00190 if (itsRegionOutFile->is_open() == false)
00191 LFATAL("Cannot open '%s' for writing", itsRegionOutFname.getVal().c_str());
00192 }
00193
00194
00195 if (!(itsRegionOutFname.getVal().empty()) && itsDisplayPatch.getVal() == false)
00196 LFATAL("Cannot write %s unless --display-patch is set.",
00197 itsRegionOutFname.getVal().c_str());
00198
00199
00200
00201 if(itsRandomColoring.getVal())
00202 for (uint i = 0; i < itsNumObjects; i++)
00203 itsRandColors.push_back(PixRGB<byte>(randomUpToIncluding(255),
00204 randomUpToIncluding(255),
00205 randomUpToIncluding(255)));
00206
00207 SimulationViewerEyeMvt::start1();
00208 }
00209
00210
00211 void SimulationViewerEyeRegion::stop1()
00212 {
00213 GVX_TRACE(__PRETTY_FUNCTION__);
00214 if (itsRegionOutFile) {
00215 writeROIOutput(rawToRet(itsObjectEntry->position()));
00216 delete itsRegionOutFile;
00217 itsRegionOutFile = 0;
00218 }
00219
00220 SimulationViewerEyeMvt::stop1();
00221 }
00222
00223
00224 uint SimulationViewerEyeRegion::findHitRegion(const Point2D<int> pt, uint fNum)
00225 {
00226
00227
00228
00229
00230
00231 if(itsObjectsInfo.get() == 0)
00232 LFATAL("No objects data - check xml file.");
00233
00234 if(itsFrameNumber >= itsObjectsInfo->getNumScenes())
00235 {
00236 LINFO("Ran out of XML scene data...");
00237 return NULL_OBJ;
00238 }
00239
00240
00241
00242 Scene sceneData =
00243 itsObjectsInfo->getSceneData(fNum);
00244
00245
00246 uint pID = NULL_OBJ;
00247 double thisrank, maxrank=-1;
00248
00249 for(std::vector<Object>::iterator itrObject =
00250 sceneData.objects.begin(); itrObject != sceneData.objects.end(); itrObject++)
00251 if(pnpoly((*itrObject).polygon,pt))
00252 {
00253 thisrank = rankForeground(*itrObject);
00254 if(thisrank > maxrank)
00255 {
00256 pID = (*itrObject).id;
00257 maxrank = thisrank;
00258 }
00259 }
00260 return pID;
00261 }
00262
00263
00264
00265 double SimulationViewerEyeRegion::rankForeground(Object obj)
00266 {
00267
00268
00269 const int h=1080,w=1920;
00270 const double scrsize= h*w;
00271 const size_t npos = std::string::npos;
00272
00273
00274 std::string name = toLowerCase(getObjName(obj.id));
00275 if(name.find("eyes") != npos || name.find("mouth") != npos) return 4.0;
00276 if(name.find("head") != npos || name.find("face") != npos) return 3.0;
00277 if(name.find("body") != npos) return 2.0;
00278 if(name.find("man") != npos || name.find("guy") != npos ||
00279 name.find("girl") != npos || name.find("person") != npos ||
00280 name.find("people") != npos || name.find("group") != npos)
00281 return area(obj.polygon)/scrsize+1;
00282 if(obj.id == NULL_OBJ) return 0;
00283 else return 1-area(obj.polygon)/scrsize;
00284
00285 }
00286
00287
00288 std::string SimulationViewerEyeRegion::listAllRegionsHit(const Point2D<int> pt, uint fNum)
00289 {
00290 if(itsObjectsInfo.get() == 0)
00291 LFATAL("No objects data - check xml file.");
00292
00293 if(itsFrameNumber >= itsObjectsInfo->getNumScenes())
00294 {
00295 LINFO("Ran out of XML scene data...");
00296 return std::string();
00297 }
00298
00299
00300
00301 Scene sceneData =
00302 itsObjectsInfo->getSceneData(fNum);
00303
00304
00305 std::string hits;
00306
00307 for(std::vector<Object>::iterator itrObject =
00308 sceneData.objects.begin(); itrObject != sceneData.objects.end(); itrObject++)
00309 if(pnpoly((*itrObject).polygon,pt))
00310 {
00311 if (!hits.empty()) hits += ";";
00312 hits += getObjName((*itrObject).id);
00313 }
00314
00315 if (hits.empty())
00316 {
00317 LINFO("nothing hit!");
00318 hits = "none";
00319 }
00320 return hits;
00321 }
00322
00323 void SimulationViewerEyeRegion::extraSampleProcessing(const rutz::shared_ptr<EyeData> data)
00324 {
00325 Point2D<int> currPos = rawToRet(data->position());
00326 uint hitObjID = findHitRegion(currPos);
00327
00328 if(hitObjID != itsCurrRegionID)
00329 {
00330
00331
00332 writeROIOutput(currPos);
00333
00334
00335
00336
00337
00338 Object oldObj = getSceneObj(itsCurrRegionID, itsObjectFrameOnset),
00339 newObj = getSceneObj(hitObjID);
00340
00341
00342
00343
00344
00345
00346 itsCurrRegionID = hitObjID;
00347 itsObjectOnset = itsCurrTime;
00348 itsObjectFrameOnset = itsFrameNumber;
00349 itsObjectEntry = data;
00350 }
00351 }
00352
00353
00354 void SimulationViewerEyeRegion::writeROIOutput(Point2D<int> currPos)
00355 {
00356
00357
00358
00359
00360 if(itsObjectsInfo.get() == 0)
00361 LFATAL("No objects data - check xml file.");
00362 if(itsFrameNumber >= itsObjectsInfo->getNumScenes())
00363 {
00364 LINFO("Ran out of XML scene data...");
00365 return;
00366 }
00367
00368
00369 if (itsRegionOutFname.getVal().empty()) return;
00370
00371
00372 if (!itsRegHeaderWritten)
00373 {
00374 itsRegHeaderWritten = true;
00375
00376 std::string header;
00377 header += "objname onset duration ";
00378 for(std::vector<std::string>::iterator iStr = itsObjectsNames.begin();
00379 iStr != itsObjectsNames.end(); iStr++)
00380 header += sformat("%sDist ", (*iStr).c_str());
00381
00382 if (itsRegionOutFile)
00383 (*itsRegionOutFile) << header << std::endl;
00384
00385
00386
00387 }
00388
00389 std::string output;
00390
00391
00392 Object thisObj =
00393 getSceneObj(itsCurrRegionID,itsObjectFrameOnset);
00394 output += sformat("%s ", getObjName(thisObj.id).c_str());
00395
00396
00397 output += sformat("%.1fms ", itsObjectOnset.msecs());
00398
00399 output += sformat("%.1fms ", (itsCurrTime-itsObjectOnset).msecs());
00400
00401
00402
00403
00404 const uint N = 5;
00405 uint iFrame;
00406
00407 double dist;
00408 const double NOT_IN_FRAME = 10000;
00409 std::vector<std::vector<double> > distsNow
00410 (itsNumObjects, std::vector<double>(N,NOT_IN_FRAME));
00411
00412 for(uint i = 0; i < N; i++)
00413 {
00414 iFrame = itsObjectFrameOnset + uint((itsFrameNumber-itsObjectFrameOnset)*i/N);
00415 Scene sceneData =
00416 itsObjectsInfo->getSceneData(iFrame);
00417
00418
00419 std::vector<Object>::iterator itr;
00420 for(itr = sceneData.objects.begin(); itr != sceneData.objects.end(); itr++)
00421 {
00422 std::string objName = getObjName((*itr).id);
00423 std::vector<Point2D<int> > objPoly = (*itr).polygon;
00424 uint ps = objPoly.size();
00425 uint objID = (*itr).id;
00426
00427
00428 double mindist = 10000;
00429 for (uint ii = 0, jj = ps-1; ii < ps; jj = ii++)
00430 {
00431 dist = currPos.distanceToSegment(objPoly[ii],objPoly[jj]);
00432 if(mindist > dist) mindist = dist;
00433 }
00434
00435
00436 distsNow[objID][i] = (pnpoly(objPoly,currPos)) ?
00437 -mindist : mindist;
00438 }
00439 }
00440
00441 uint nPts;
00442 for(uint i = 0; i < itsNumObjects; i++)
00443 {
00444 nPts = 0;
00445 dist = 0;
00446 for(uint j = 0; j < N; j++)
00447 {
00448
00449 if(distsNow[i][j] != NOT_IN_FRAME) nPts++;
00450 dist += distsNow[i][j];
00451 }
00452 if (nPts == 0) output += "NaN ";
00453 else output += sformat("%0.3f ", dist/nPts);
00454 }
00455
00456 if (itsRegionOutFile)
00457 (*itsRegionOutFile) << output << std::endl;
00458 }
00459
00460
00461 void SimulationViewerEyeRegion::drawEye(const rutz::shared_ptr<EyeData> rawPos, const uint tN)
00462 {
00463
00464
00465
00466
00467 const PixRGB<byte> col = itsEyeStyles[tN].col;
00468 if(itsFrameNumber >= itsObjectsInfo->getNumScenes())
00469 {
00470 LINFO("Ran out of XML scene data... (%d/%d)",itsFrameNumber,
00471 itsObjectsInfo->getNumScenes());
00472 return;
00473 }
00474
00475
00476
00477
00478
00479 if(itsHighlightMode.getVal().compare("traced") == 0)
00480 {
00481 Object currObj =
00482 getSceneObj(itsCurrRegionID);
00483
00484 drawFilledPolygon(itsTargetsMask, currObj.polygon, col);
00485 drawRegions(currObj);
00486 }
00487 if(itsObjectDrawMode.getVal().compare("traced") == 0)
00488 {
00489 Object currObj =
00490 getSceneObj(itsCurrRegionID);
00491 drawRegions(currObj);
00492 }
00493 SimulationViewerEyeMvt::drawEye(rawPos, tN);
00494 }
00495
00496
00497 void SimulationViewerEyeRegion::drawFOA(const Point2D<int> target, const uint tN)
00498 {
00499 const PixRGB<byte> col = itsEyeStyles[tN].col;
00500 if(itsFrameNumber >= itsObjectsInfo->getNumScenes())
00501 {
00502 LINFO("Ran out of XML scene data...");
00503 return;
00504 }
00505
00506 if(itsHighlightMode.getVal().compare("targeted") == 0)
00507 {
00508 uint hitObjID = findHitRegion(target);
00509 Object thisObj =
00510 getSceneObj(hitObjID);
00511 drawFilledPolygon(itsTargetsMask, thisObj.polygon, col);
00512 drawRegions(thisObj);
00513 }
00514 if(itsObjectDrawMode.getVal().compare("targeted") == 0)
00515 {
00516 uint hitObjID = findHitRegion(target);
00517 Object thisObj =
00518 getSceneObj(hitObjID);
00519 drawRegions(thisObj);
00520 }
00521
00522 SimulationViewerEyeMvt::drawFOA(target,tN);
00523 }
00524
00525
00526 void SimulationViewerEyeRegion::drawRegions(Object myObj)
00527 {
00528 if(itsObjectsInfo.get() == 0)
00529 LFATAL("No objects data - check xml file.");
00530
00531
00532 if(itsFrameNumber >= itsObjectsInfo->getNumScenes())
00533 {
00534 LINFO("Ran out of XML scene data...");
00535 return;
00536 }
00537
00538 Image<PixRGB<byte> > shapes(itsDrawings.getDims(),ZEROS);
00539
00540 Scene sceneData = itsObjectsInfo->getSceneData(itsFrameNumber);
00541 if(myObj.id!=NULL_OBJ || itsObjectDrawMode.getVal().compare("all") != 0)
00542 {
00543 PixRGB<byte> lineCol(0,255,0);
00544 if (itsRandomColoring.getVal())
00545 lineCol = itsRandColors[myObj.id];
00546
00547
00548 drawOutlinedPolygon(shapes, myObj.polygon,
00549 lineCol,
00550 Point2D<int>(0,0), 0, 1.0, 0, 0,
00551 itsLineThickness.getVal());
00552
00553
00554
00555
00556 Point2D<int> cm = centroid(myObj.polygon);
00557 Point2D<int> upperleft = cm - Point2D<int>(-10,10);
00558
00559 double thisDist, maxDist = 0;
00560 Point2D<int> refPt = myObj.polygon[0];
00561 for(uint i = 0; i < myObj.polygon.size(); i++) {
00562 thisDist = myObj.polygon[i].distanceToLine(cm, upperleft, true);
00563 if (thisDist > maxDist) {
00564 maxDist = thisDist;
00565 refPt = myObj.polygon[i];
00566 }
00567 }
00568
00569 writeText(itsDrawings, refPt+Point2D<int>(10,5),
00570 getObjName(myObj.id).c_str(),
00571 PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0),
00572 SimpleFont::FIXED(10), true);
00573 }
00574 else {
00575 Scene thisScene = itsObjectsInfo->getSceneData(itsFrameNumber);
00576 for (std::vector<Object>::iterator iObj = thisScene.objects.begin();
00577 iObj != thisScene.objects.end(); iObj++)
00578 drawRegions(*iObj);
00579 }
00580 itsDrawings = composite(itsDrawings,shapes);
00581 }
00582
00583
00584
00585 Object SimulationViewerEyeRegion::getSceneObj(uint objID, uint FrameNum)
00586 {
00587 Object non_object = Object();
00588 non_object.name = getObjName(NULL_OBJ);
00589 non_object.id = NULL_OBJ;
00590 if(objID == NULL_OBJ) return non_object;
00591 ASSERT(FrameNum < itsObjectsInfo->getNumScenes());
00592
00593 Scene sceneData = itsObjectsInfo->getSceneData(FrameNum);
00594 for(std::vector<Object>::iterator itrObject =
00595 sceneData.objects.begin(); itrObject != sceneData.objects.end(); itrObject++)
00596 if ((*itrObject).id==objID) return (*itrObject);
00597
00598 return non_object;
00599 }
00600
00601
00602 std::string SimulationViewerEyeRegion::getObjName(uint objID)
00603 {
00604 if(objID == NULL_OBJ) return "none";
00605 else if(objID >= itsNumObjects) LFATAL("%d illegal index (max = %d, null = %d)", objID, itsNumObjects, NULL_OBJ);
00606 return itsObjectsNames[objID];
00607 }
00608
00609
00610 std::string SimulationViewerEyeRegion::craftSVEMOutput(const std::string tfn,
00611 const rutz::shared_ptr<EyeData> data)
00612 {
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624 std::string output = SimulationViewerEyeMvt::craftSVEMOutput(tfn,data);
00625
00626
00627 output += craftRegionOutput(data);
00628
00629 return output;
00630 }
00631
00632
00633 std::string SimulationViewerEyeRegion::
00634 craftRegionOutput(const rutz::shared_ptr<EyeData> data)
00635 {
00636 std::string output;
00637
00638
00639 Point2D<int> position = rawToRet(data->position());
00640 Point2D<int> sacTarget = rawToRet(data->saccadeTarget());
00641 bool giveAllRegions = true;
00642 if(giveAllRegions)
00643 {
00644 uint destObjID = findHitRegion(sacTarget);
00645 output += sformat(" %s %s %s %s",
00646 getObjName(itsCurrRegionID).c_str(),
00647 listAllRegionsHit(position).c_str(),
00648 getObjName(destObjID).c_str(),
00649 listAllRegionsHit(sacTarget).c_str());
00650
00651 if(!itsHeaderCrafted)
00652 {
00653 itsOutFields.push_back("bestregion_src");
00654 itsOutFields.push_back("region_src");
00655 itsOutFields.push_back("bestregion_target");
00656 itsOutFields.push_back("region_target");
00657 }
00658 }
00659 else
00660 {
00661 uint destObjID = findHitRegion(sacTarget);
00662 output += sformat(" %s %s",
00663 getObjName(itsCurrRegionID).c_str(),
00664
00665 getObjName(destObjID).c_str());
00666 if(!itsHeaderCrafted)
00667 {
00668 itsOutFields.push_back("region_src");
00669 itsOutFields.push_back("region_target");
00670 }
00671
00672 }
00673 return output;
00674 }
00675
00676
00677 Image< PixRGB<byte> > SimulationViewerEyeRegion::getTraj(SimEventQueue& q)
00678 {
00679 LDEBUG("Buffering output frame %d...", itsFrameNumber);
00680
00681 GVX_TRACE(__PRETTY_FUNCTION__);
00682
00683 Image< PixRGB<byte> > input;
00684 if (SeC<SimEventRetinaImage> e = q.check<SimEventRetinaImage>(this, SEQ_ANY))
00685 {
00686 input = e->frame().colorByte();
00687
00688 if(itsObjectDrawMode.getVal().compare("all") == 0)
00689 drawRegions();
00690 else if(itsObjectDrawMode.getVal().compare("selected") == 0 &&
00691 !itsSelectedObjects.getVal().empty())
00692 {
00693 Scene sceneData = itsObjectsInfo->getSceneData(itsFrameNumber);
00694 for(uint i = 0; i < itsObjectsInfo->getNumObj(itsFrameNumber); i++)
00695 {
00696 Object objData = sceneData.objects[i];
00697
00698
00699
00700 std::string objName = getObjName(objData.id);
00701
00702 drawRegions(objData);
00703 }
00704 }
00705 }
00706 else
00707 LFATAL("Could not find required SimEventRetinaImage");
00708
00709
00710 if(itsTargetsMask.initialized()) {
00711 input = alphaBlend(itsTargetsMask, input,
00712 itsHitTransparency.getVal());
00713 }
00714
00715
00716 itsTargetsMask.resize(input.getDims(), true);
00717
00718
00719 Image<PixRGB<byte> > comp = composite(itsDrawings, input);
00720
00721
00722 if (itsSaveTraj.getVal()) return comp;
00723
00724
00725 const Dims dims = input.getDims();
00726 Image<float> sm = getMap(q, false);
00727 if (sm.initialized()) sm = rescaleOpt(sm, dims, itsDisplayInterp.getVal());
00728 else sm.resize(dims, true);
00729 Image< PixRGB<byte> > smc = toRGB(Image<byte>(sm));
00730
00731
00732 Image< PixRGB<byte> > smcomp = composite(itsDrawings, smc);
00733
00734
00735
00736
00737 Image< PixRGB<byte> > ret;
00738 if (itsMaxCacheSize.getVal())
00739 {
00740
00741 Image<float> maxsm =
00742 rescaleOpt(itsMaxCache.getMax(), dims, itsDisplayInterp.getVal());
00743 Image< PixRGB<byte> > maxsmc = toRGB(Image<byte>(maxsm));
00744
00745 ret = concatX(concatY(input, smcomp),
00746 concatY(comp, composite(itsDrawings, maxsmc)));
00747
00748 drawGrid(ret, dims.w()-1, dims.h()-1, 3, 3, PixRGB<byte>(128, 128, 128));
00749 }
00750 else
00751 {
00752
00753 ret = concatX(comp, smcomp);
00754 drawLine(ret, Point2D<int>(dims.w()-1, 0), Point2D<int>(dims.w()-1, dims.h()-1),
00755 PixRGB<byte>(255, 255, 0), 1);
00756 drawLine(ret, Point2D<int>(dims.w(), 0), Point2D<int>(dims.w(), dims.h()-1),
00757 PixRGB<byte>(255, 255, 0), 1);
00758 }
00759
00760
00761 while (ret.getWidth() > itsMaxComboWidth.getVal())
00762 ret = decY(lowPass3y(decX(lowPass3x(ret))));
00763
00764 return ret;
00765 }
00766
00767
00768
00769
00770
00771
00772