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 #ifndef PSYCHO_ARRAYCREATOR_C_DEFINED
00037 #define PSYCHO_ARRAYCREATOR_C_DEFINED
00038
00039 #include "Psycho/ArrayCreator.H"
00040
00041 #include "Component/ModelOptionDef.H"
00042 #include "Util/StringConversions.H"
00043 #include "Util/StringUtil.H"
00044 #include "Image/DrawOps.H"
00045
00046 #include <iostream>
00047 #include <fstream>
00048
00049 const ModelOptionCateg MOC_PSYCHOARRAYCREATOR = {
00050 MOC_SORTPRI_2, "ArrayCreator realted options" };
00051
00052
00053 const ModelOptionDef OPT_ACFileName =
00054 { MODOPT_ARG_STRING, "ACFileName", &MOC_PSYCHOARRAYCREATOR, OPTEXP_CORE,
00055 "File name of configuration file for ArrayCreator",
00056 "ac-filename", '\0', "<filename>", "array_config.conf" };
00057
00058
00059 const ModelOptionDef OPT_ACItemRadius =
00060 { MODOPT_ARG(uint), "ACItemRadius", &MOC_PSYCHOARRAYCREATOR,
00061 OPTEXP_CORE,
00062 "default radius to use for array items, in degrees of visual angle",
00063 "ac-itemradius", '\0', "<uint>", "2" };
00064
00065
00066 const ModelOptionDef OPT_ACJitterLevel =
00067 { MODOPT_ARG(float), "ACJitterLevel", &MOC_PSYCHOARRAYCREATOR,
00068 OPTEXP_CORE, "The default off-grid jitter of the items, "
00069 "in degrees of visual angle", "ac-jitter", '\0', "<float>", "1" };
00070
00071
00072 const ModelOptionDef OPT_ACBackgroundColor =
00073 { MODOPT_ARG(PixRGB<byte>), "ACBackgroundColor", &MOC_PSYCHOARRAYCREATOR,
00074 OPTEXP_CORE, "value of the default background pixel, in RGB",
00075 "ac-bgcolor", '\0', "<byte,byte,byte>", "128,128,128" };
00076
00077
00078 const ModelOptionDef OPT_ACPpdX =
00079 { MODOPT_ARG(float), "ACPpdX", &MOC_PSYCHOARRAYCREATOR,
00080 OPTEXP_CORE, "pixels per degree for x direction",
00081 "ac-ppdx", '\0', "<float>", "10.0" };
00082
00083
00084 const ModelOptionDef OPT_ACPpdY =
00085 { MODOPT_ARG(float), "ACPpdY", &MOC_PSYCHOARRAYCREATOR,
00086 OPTEXP_CORE, "pixels per degree for y direction",
00087 "ac-ppdy", '\0', "<float>", "10.0" };
00088
00089
00090 const ModelOptionDef OPT_ACPermuteTargs =
00091 { MODOPT_FLAG, "ACPermuteTargs", &MOC_PSYCHOARRAYCREATOR,
00092 OPTEXP_CORE, "Display more than one target at a time?",
00093 "ac-perm-targs", '\0', "<bool>", "true" };
00094
00095
00096
00097
00098
00099 std::string convertToString(const ItemType& item)
00100 {
00101 switch (item)
00102 {
00103 case BARH:
00104 return std::string("BARH");
00105 case BARV:
00106 return std::string("BARV");
00107 case CIRCLE:
00108 return std::string("CIRCLE");
00109 case SQUARE:
00110 return std::string("SQUARE");
00111 case BLOB:
00112 return std::string("BLOB");
00113 default:
00114 {
00115 LFATAL("No such item type");
00116 return std::string();
00117 }
00118 }
00119 }
00120
00121
00122 void convertFromString(const std::string& str, ItemType& itemtype)
00123 {
00124 if (str.compare("SQUARE") == 0)
00125 itemtype = SQUARE;
00126 else if (str.compare("BLOB") == 0)
00127 itemtype = BLOB;
00128 else if (str.compare("CIRCLE") == 0)
00129 itemtype = CIRCLE;
00130 else if (str.compare("BARH") == 0)
00131 itemtype = BARH;
00132 else if (str.compare("BARV") == 0)
00133 itemtype = BARV;
00134 else
00135 LFATAL("No such search array item option.");
00136 }
00137
00138
00139 std::string convertToString(const ColorSpace& colorspace)
00140 {
00141 switch (colorspace)
00142 {
00143 case RGB:
00144 return std::string("RGB");
00145 case HSV:
00146 return std::string("HSV");
00147 case DKL:
00148 return std::string("DKL");
00149 default:
00150 {
00151 LFATAL("No ColorSpace set");
00152 return std::string();
00153 }
00154 }
00155 }
00156
00157
00158 void convertFromString(const std::string& str, ColorSpace& itemtype)
00159 {
00160 if (str.compare("HSV") == 0)
00161 itemtype = HSV;
00162 else if (str.compare("RGB") == 0)
00163 itemtype = RGB;
00164 else if (str.compare("DKL") == 0)
00165 itemtype = DKL;
00166 else
00167 LFATAL("No such color space option.");
00168 }
00169
00170
00171
00172
00173 template <typename PIXEL_TYPE>
00174 ArrayItem::ArrayItem(const uint xpos, const uint ypos, const uint radius,
00175 const PIXEL_TYPE& color, const float& orientation) :
00176 itsPos(xpos,ypos), itsRad(radius), itsCol(color), itsOrient(orientation)
00177 {
00178 }
00179
00180
00181 ArrayItem::~ArrayItem()
00182 {
00183 }
00184
00185
00186 std::string ArrayItem::toString() const
00187 {
00188 std::string str = toStr<uint>(itsPos.x()) + ":" + toStr<uint>(itsPos.y()) +
00189 ":" + toStr<int>(itsRad) + ":" + toStr<PixRGB<byte> >(itsCol) + ":" +
00190 toStr<float>(itsOrient) + ":" + getShapeName();
00191 return str;
00192 }
00193
00194
00195 template <class PIXEL_TYPE>
00196 BarItem::BarItem(const uint xpos, const uint ypos, const uint radius,
00197 const PIXEL_TYPE& color, const float& orientation) :
00198 ArrayItem(xpos,ypos,radius,color,orientation)
00199 {
00200 }
00201
00202
00203 BarItem::~BarItem()
00204 {
00205 }
00206
00207
00208 std::string BarItem::getShapeName() const
00209 {
00210 return "BAR";
00211 }
00212
00213
00214 void BarItem::drawItem(Image<PixRGB<byte> >& dst) const
00215 {
00216 int tt = (int)(getPos().y() - getRad());
00217 int bb = (int)(getPos().y() + getRad());
00218 int ll = (int)((float)getPos().x() - getRad()/3.0f);
00219 int rr = (int)((float)getPos().x() + getRad()/3.0f);
00220 while ( ((bb - tt) > 0) && ((rr - ll) > 0) )
00221 {
00222 tt++; bb--; ll++; rr--;
00223 Rectangle r = Rectangle::tlbrO(tt, ll, bb, rr);
00224 drawRectOR(dst, r, getCol(), 1, getOrient());
00225 }
00226 }
00227
00228
00229 template <class PIXEL_TYPE>
00230 CircleItem::CircleItem(const uint xpos, const uint ypos, const uint radius,
00231 const PIXEL_TYPE& color, const float& orientation) :
00232 ArrayItem(xpos,ypos,radius,color,orientation)
00233 {
00234 }
00235
00236
00237 CircleItem::~CircleItem()
00238 {
00239 }
00240
00241
00242 std::string CircleItem::getShapeName() const
00243 {
00244 return "CIRCLE";
00245 }
00246
00247
00248 void CircleItem::drawItem(Image<PixRGB<byte> >& dst) const
00249 {
00250 drawDisk(dst, Point2D<int>((int)getPos().x(),(int)getPos().y()),
00251 getRad(), getCol());
00252 }
00253
00254
00255 template <class PIXEL_TYPE>
00256 SquareItem::SquareItem(const uint xpos, const uint ypos, const uint radius,
00257 const PIXEL_TYPE& color, const float& orientation) :
00258 ArrayItem(xpos,ypos,radius,color,orientation)
00259 {
00260 }
00261
00262
00263 SquareItem::~SquareItem()
00264 {
00265 }
00266
00267
00268 std::string SquareItem::getShapeName() const
00269 {
00270 return "SQUARE";
00271 }
00272
00273
00274 void SquareItem::drawItem(Image<PixRGB<byte> >& dst) const
00275 {
00276 drawPatch(dst, Point2D<int>((int)getPos().x(),(int)getPos().y()),
00277 getRad(), getCol());
00278 }
00279
00280
00281 template <class PIXEL_TYPE>
00282 BlobItem::BlobItem(const uint xpos, const uint ypos, const uint radius,
00283 const PIXEL_TYPE& color, const float& orientation) :
00284 ArrayItem(xpos,ypos,radius,color,orientation)
00285 {
00286 }
00287
00288
00289 BlobItem::~BlobItem()
00290 {
00291 }
00292
00293
00294 std::string BlobItem::getShapeName() const
00295 {
00296 return "BLOB";
00297 }
00298
00299
00300 void BlobItem::drawItem(Image<PixRGB<byte> >& dst) const
00301 {
00302 float stddev = (float)getRad()/2;
00303 int psize = stddev*2;
00304
00305 int ux = int(getPos().x()) - psize;
00306 int step = dst.getWidth() - 2 * psize-1;
00307
00308 Image<PixRGB<byte> >::iterator dptr = dst.beginw() +
00309 int(getPos().y() - psize) * dst.getWidth() + ux;
00310
00311 for (int y = -1*psize; y <= psize; y++)
00312 {
00313 float resultX,resultY;
00314 resultY = exp(-(float(y*y)/(stddev*stddev)));
00315 for (int x = -1*psize; x <= psize; x++)
00316 {
00317 resultX = exp(-((x*x)/(stddev*stddev)));
00318 float g = resultX*resultY;
00319
00320
00321 PixRGB<byte> col = getCol();
00322 col *= g;
00323 *dptr *= (1-g);
00324 (*dptr++) += col;
00325 }
00326 dptr += step;
00327 }
00328 }
00329
00330
00331
00332
00333 ArrayCreator::ArrayCreator(const std::string& filename, const float& radius,
00334 const float& noise, const Dims& dims,
00335 const float& ppdx, const float& ppdy,
00336 const PixRGB<byte>& background,
00337 const float& fix_size, const bool permTargs) :
00338 itsRF(), itsColT(), itsColD(), itsDist(), itsShape(),
00339 itsStims(), itsDescr(), itsDims(dims), itsRad(radius), itsNoise(noise),
00340 itsPpdx(ppdx), itsPpdy(ppdy), itsPpd(sqrt(ppdx*ppdx + ppdy*ppdy)),
00341 itsBackgroundColor(background), itsFixSize(fix_size), rnum((int)time(NULL)),
00342 itsPermTargs(permTargs)
00343 {
00344 parseFile(filename);
00345 computeSequence();
00346
00347 }
00348
00349
00350 ArrayCreator::~ArrayCreator()
00351 {
00352 for (size_t ii = 0; ii < itsStims.size(); ++ii)
00353 for (size_t jj = 0; jj < itsStims.size(); ++jj)
00354 delete itsStims[ii][jj];
00355 }
00356
00357
00358 uint ArrayCreator::size() const
00359 {
00360 return (uint)itsStims.size();
00361 }
00362
00363
00364 Image<PixRGB<byte> > ArrayCreator::draw(const uint permnum) const
00365 {
00366 Image<PixRGB<byte> > img(itsDims, ZEROS);
00367 img += itsBackgroundColor;
00368 draw(img, permnum);
00369 return img;
00370 }
00371
00372
00373 void ArrayCreator::draw(Image<PixRGB<byte> >& dst, const uint permnum) const
00374 {
00375 if (dst.getDims() != itsDims)
00376 LFATAL("Image dimensions must be the same as those specified at "
00377 "this objects creation. ");
00378
00379 std::vector<ArrayItem*> temp = itsStims[permnum];
00380 std::vector<ArrayItem*>::iterator iter = temp.begin();
00381 while (iter != temp.end())
00382 (*iter++)->drawItem(dst);
00383
00384 if (itsFixSize > 0)
00385 {
00386 int size = int(itsFixSize * itsPpd);
00387 if ((size % 2) == 0)
00388 size = size / 2;
00389 else
00390 size = (size - 1) / 2;
00391 const int i = itsDims.w()/2-1,j = itsDims.h()/2-1;
00392 Rectangle frect = Rectangle::tlbrI(j-size+1, i-size+1,
00393 j + size, i + size);
00394 drawFilledRect(dst, frect, PixRGB<byte>(255,255,255));
00395 }
00396 }
00397
00398
00399 std::string ArrayCreator::toString(const uint permnum) const
00400 {
00401 return itsDescr[permnum];
00402 }
00403
00404
00405 void ArrayCreator::parseFile(const std::string& file)
00406 {
00407
00408 std::ifstream f(file.c_str());
00409 if (!f.is_open())
00410 LFATAL("Couldn't open '%s' for reading.",file.c_str());
00411 LINFO("%s opened for reading",file.c_str());
00412
00413
00414 std::string line = readLine(f);
00415 while (line.find(':') == std::string::npos)
00416 {
00417 std::vector<std::string> tok;
00418 split(line, ",", std::back_inserter(tok));
00419 int xpix = int((float)fromStr<int>(tok[0]) * itsPpdx + itsDims.w()/2);
00420 int ypix = int((float)fromStr<int>(tok[1]) * itsPpdy + itsDims.h()/2);
00421 if (((int)xpix < itsDims.w()) && ((int)ypix < itsDims.h()) &&
00422 (xpix >=0) && (ypix >=0))
00423 {
00424 float size = fromStr<float>(tok[2]) * itsPpd;
00425 RF r = {geom::vec2<uint>((uint)xpix,(uint)ypix), size};
00426 itsRF.push_back(r);
00427 }
00428 line = readLine(f);
00429 }
00430 LINFO("%d RF's and other target locations",(int)itsRF.size());
00431
00432
00433 std::vector<std::string> tok;
00434 split(line, " ", std::back_inserter(tok));
00435 for (size_t ii = 0; ii < tok.size(); ++ii)
00436 {
00437 std::vector<std::string> tok1;
00438 split(tok[ii], ":", std::back_inserter(tok1));
00439 std::string type = tok1[0];
00440 ColorSpace cs = RGB;
00441 convertFromString(tok1[1], cs);
00442 switch (cs)
00443 {
00444 case RGB:
00445 {
00446 (type.compare("T") == 0)?
00447 itsColT.push_back(fromStr<PixRGB<byte> >(tok1[2])):
00448 itsColD.push_back(fromStr<PixRGB<byte> >(tok1[2]));
00449 break;
00450 }
00451 case HSV:
00452 {
00453 PixHSV<byte> thsv(fromStr<PixHSV<byte> >(tok1[2]));
00454 PixRGB<byte> tmp(thsv);
00455 (type.compare("T") == 0)?
00456 itsColT.push_back(tmp):
00457 itsColD.push_back(tmp);
00458 break;
00459 }
00460 case DKL:
00461 {
00462 LFATAL("DKL Colorspace options are currently unfunctional, "
00463 "please use HSV, or RGB");
00464
00465
00466 break;
00467 }
00468 default:
00469 {
00470 LFATAL("No ColorSpace set");
00471 break;
00472 }
00473 }
00474 }
00475
00476 LINFO("%d targets and %d distractors color conditions",
00477 (int)itsColT.size(), (int)itsColD.size());
00478
00479
00480 line = readLine(f);
00481 tok.clear();
00482 split(line, " ", std::back_inserter(tok));
00483 for (size_t ii = 0; ii < tok.size(); ++ii)
00484 itsDist.push_back(fromStr<uint>(tok[ii]));
00485 LINFO("%d distractor set sizes",(int)itsDist.size());
00486
00487
00488 line = readLine(f);
00489 tok.clear();
00490 split(line, " ", std::back_inserter(tok));
00491 for (size_t ii = 0; ii < tok.size(); ++ii)
00492 {
00493 std::vector<std::string> ttok;
00494 split(tok[ii], "-", std::back_inserter(ttok));
00495 if (ttok.size() > 2)
00496 LFATAL("Cannot have more than two paired shapes");
00497
00498 std::vector<ItemType> tempv;
00499 for (size_t jj = 0; jj < ttok.size(); ++jj)
00500 {
00501 ItemType it = SQUARE;
00502 convertFromString(ttok[jj], it);
00503 tempv.push_back(it);
00504 }
00505 itsShape.push_back(tempv);
00506 }
00507 LINFO("%d shape conditions", (int)itsShape.size());
00508 f.close();
00509 }
00510
00511
00512 std::string ArrayCreator::readLine(std::ifstream& fs)
00513 {
00514 using namespace std;
00515 string line = "#";
00516
00517 if (fs.eof())
00518 return line;
00519
00520 while (line[0] == '#')
00521 getline(fs, line);
00522
00523 return line;
00524 }
00525
00526
00527 void ArrayCreator::computeSequence()
00528 {
00529
00530
00531
00532
00533
00534
00535 std::vector<std::vector<int> > idx;
00536
00537
00538 if (itsPermTargs)
00539 {
00540 std::vector<int> t;
00541 t.push_back(0);
00542 idx.push_back(t);
00543 subset(idx, (int)itsRF.size());
00544 t.resize(0);
00545 t.push_back(-1);
00546 idx.push_back(t);
00547 }
00548 else
00549 for (uint ii = 0; ii < itsRF.size(); ++ii)
00550 {
00551 std::vector<int> t;
00552 t.push_back(ii);
00553 idx.push_back(t);
00554 }
00555
00556
00557
00558
00559
00560 if (itsColT.size() > 2)
00561 LFATAL("currently only two target types are supported");
00562
00563
00564 for (uint ccd = 0; ccd < itsColD.size(); ++ccd)
00565 for (uint cct1 = 0; cct1 < itsColT.size(); ++cct1)
00566 for (uint cct2 = cct1; cct2 < itsColT.size(); ++cct2)
00567 for (uint dd = 0; dd < itsDist.size(); ++dd)
00568 for (uint ss = 0; ss < itsShape.size(); ++ss)
00569 for (uint sst = 0; sst < itsShape[ss].size(); ++sst)
00570 for (uint ssd = 0; ssd < itsShape[ss].size(); ++ssd)
00571 if ((sst != ssd) || (itsShape[ss].size() == 1))
00572 for (uint id = 0; id < idx.size(); ++id)
00573 for (uint tp = 0; tp < idx[id].size(); ++tp)
00574 {
00575
00576
00577
00578
00579 if ((itsDist[dd] == 0) && (idx[id][0] == -1))
00580 continue;
00581
00582
00583
00584
00585 if ((idx[id].size() == 1) && (cct1 != cct2))
00586 continue;
00587
00588
00589
00590
00591 if ((cct1 == cct2) && (tp > 0))
00592 continue;
00593
00594
00595
00596 std::vector<geom::vec2<uint> > grid = getGrid(idx[id]);
00597
00598
00599
00600 std::random_shuffle(grid.begin(), grid.end());
00601 if (itsDist[dd] < grid.size())
00602 grid.resize(itsDist[dd]);
00603
00604 std::vector<ArrayItem*> array;
00605 std::string arraydescr, conddescr;
00606
00607
00608 for (uint ii = 0; ii < grid.size(); ++ii)
00609 {
00610 ArrayItem* ai = createItem(itsShape[ss][ssd],
00611 grid[ii],
00612 itsColD[ccd]);
00613 array.push_back(ai);
00614 arraydescr += "::D:" + ai->toString();
00615 }
00616
00617
00618
00619 std::vector<int>::iterator iter = idx[id].begin();
00620 uint otc(0), rfc(0);
00621 while (iter != idx[id].end())
00622 {
00623 if (*iter == -1)
00624 {
00625 ++iter;
00626 continue;
00627 }
00628
00629 ArrayItem* ai = NULL;
00630 if (*iter == idx[id][tp])
00631 ai = createItem(itsShape[ss][sst],
00632 itsRF[*iter].pos,
00633 itsColT[cct1]);
00634 else
00635 ai = createItem(itsShape[ss][sst],
00636 itsRF[*iter].pos,
00637 itsColT[cct2]);
00638
00639 array.push_back(ai);
00640 if (itsRF[*iter].size == 0)
00641 {
00642 arraydescr += "::OT:" + ai->toString();
00643 ++otc;
00644 }
00645 else
00646 {
00647 arraydescr += "::RF:" + ai->toString();
00648 ++rfc;
00649 }
00650 ++iter;
00651 }
00652
00653
00654
00655 conddescr += toStr<uint>(rfc) + ":";
00656
00657 conddescr += toStr<uint>(otc) + ":";
00658
00659 conddescr += toStr<PixRGB<byte> >(itsColT[cct1]) + ":";
00660
00661 conddescr += toStr<PixRGB<byte> >(itsColT[cct2]) + ":";
00662
00663 conddescr += toStr<PixRGB<byte> >(itsColD[ccd]) + ":";
00664
00665 conddescr += toStr<uint>(itsDist[dd]) + ":";
00666
00667 conddescr += toStr<ItemType>(itsShape[ss][sst]) + ":";
00668
00669 conddescr += toStr<ItemType>(itsShape[ss][ssd]);
00670
00671
00672 itsDescr.push_back(conddescr + arraydescr);
00673 itsStims.push_back(array);
00674
00675 }
00676 }
00677
00678
00679 void ArrayCreator::subset(std::vector<std::vector<int> >& sub, const uint N)
00680 {
00681 uint tu = sub.back().back()+1;
00682 if (tu < N)
00683 {
00684 std::vector<int> tv = sub.back();
00685 tv.push_back(tu);
00686 sub.push_back(tv);
00687 this->subset(sub, N);
00688 }
00689 else
00690 {
00691 std::vector<int> tv = sub.back();
00692 if (tv.size() > 1)
00693 {
00694 tv.pop_back();
00695 tv.back()+=1;
00696 sub.push_back(tv);
00697 this->subset(sub, N);
00698 }
00699 }
00700 }
00701
00702
00703 std::vector<geom::vec2<uint> >
00704 ArrayCreator::getGrid(const std::vector<int>& onpos)
00705 {
00706 std::vector<int> pos;
00707 if (onpos[0] == -1)
00708 for (size_t ii = 0; ii < itsRF.size(); ++ii)
00709 pos.push_back((int)ii);
00710 else
00711 pos = onpos;
00712
00713
00714 const int rad = int(itsRad * itsPpd + 0.5f);
00715 const int noise = int(itsNoise * itsPpd + 0.5f);
00716 const int fxsize = int(itsFixSize * itsPpd + 0.5f);
00717 const int sz = rad*2 + noise;
00718 const int sz2 = rad*2 + 2*noise;
00719
00720 Dims gsize(itsDims.w() - sz, itsDims.h() - sz);
00721 Dims nums(int((float)gsize.w() / (float)(sz2)),
00722 int((float)gsize.h() / (float)(sz2)));
00723
00724 int tx = nums.w() * sz2;
00725 int ty = nums.h() * sz2;
00726
00727 int lx = int(float(itsDims.w() - tx)/2.0f);
00728 int ly = int(float(itsDims.h() - ty)/2.0f);
00729
00730 geom::vec2<int> c(itsDims.w()/2 - 1, itsDims.h()/2 - 1);
00731 std::vector<geom::vec2<uint> > grid;
00732 for (int xx = lx; xx <= itsDims.w() - lx; xx += sz2)
00733 for (int yy = ly; yy <= itsDims.h() - ly; yy += sz2)
00734 {
00735 geom::vec2<float> polar;
00736 polar.set_polar_rad(rnum.fdraw_range(0, noise),
00737 rnum.fdraw_range(0,2*M_PI));
00738 geom::vec2<int> tv(xx + polar.x(), yy + polar.y());
00739
00740 bool use = true;
00741 std::vector<int>::const_iterator op = pos.begin();
00742 while (op != pos.end())
00743 {
00744 geom::vec2<int> rf((int)itsRF[*op].pos.x(),
00745 (int)itsRF[*op].pos.y());
00746 float d = tv.distance_to(rf);
00747 if (d <= rad*2)
00748 use = false;
00749 ++op;
00750 }
00751
00752 float dc = 10000;
00753 if (fxsize > 0)
00754 dc = tv.distance_to(c);
00755
00756 if (use && (dc > (rad + fxsize/2 + noise)))
00757 grid.push_back(geom::vec2<uint>((uint)tv.x(), (uint)tv.y()));
00758 }
00759 return grid;
00760 }
00761
00762
00763 ArrayItem* ArrayCreator::createItem(const ItemType item,
00764 const geom::vec2<uint>& pos,
00765 const PixRGB<byte>& color)
00766 {
00767 const uint rad = uint(itsRad * itsPpd + 0.5f);
00768 switch (item)
00769 {
00770 case BARH:
00771 return new BarItem(pos.x(), pos.y(), rad, color, float(M_PI/2.0));
00772 case BARV:
00773 return new BarItem(pos.x(), pos.y(), rad, color, 0);
00774 case CIRCLE:
00775 return new CircleItem(pos.x(), pos.y(), rad, color, 0);
00776 case SQUARE:
00777 return new SquareItem(pos.x(), pos.y(), rad, color, 0);
00778 case BLOB:
00779 return new BlobItem(pos.x(), pos.y(), rad, color, 0);
00780 default:
00781 {
00782 LFATAL("No such item type");
00783 return NULL;
00784 }
00785 }
00786 }
00787
00788
00789
00790
00791
00792
00793
00794
00795 #endif // PSYCHO_ARRAYCREATOR_C_DEFINED