00001
00002
00003 #include <iostream>
00004 #include <vector>
00005
00006 #include "BaseData.h"
00007 #include "Point.h"
00008 #include "ShapeTypes.h"
00009
00010 #include "SketchSpace.h"
00011 #include "Sketch.h"
00012 #include "visops.h"
00013
00014 #include "ShapeSpace.h"
00015 #include "ShapeRoot.h"
00016
00017 #include "BrickData.h"
00018 #include "ShapeBrick.h"
00019 #include "ShapePoint.h"
00020 #include "Region.h"
00021
00022
00023 namespace DualCoding {
00024
00025 BrickData::BrickData(ShapeSpace& _space,
00026 const EndPoint &_GFL, const EndPoint &_GFR,
00027 const EndPoint &_GBL, const EndPoint &_GBR,
00028 const EndPoint &_TFL, const EndPoint &_TFR,
00029 const EndPoint &_TBL, const EndPoint &_TBR)
00030 : BaseData(_space,brickDataType),
00031 GFL(_GFL), GFR(_GFR), GBL(_GBL), GBR(_GBR),
00032 TFL(_TFL), TFR(_TFR), TBL(_TBL), TBR(_TBR),
00033 centroid((GFL + GFR + GBL + GBR + TFL + TFR + TBL + TBR) / 8)
00034 {
00035 }
00036
00037
00038 DATASTUFF_CC(BrickData);
00039
00040 bool BrickData::isMatchFor(const ShapeRoot& other) const {
00041 if (!(isSameTypeAs(other) && isSameColorAs(other)))
00042 return false;
00043
00044
00045 float dist = 0;
00046 return dist < 20;
00047 }
00048
00049 void BrickData::mergeWith(const ShapeRoot& other) {
00050 const Shape<BrickData>& other_brick = ShapeRootTypeConst(other,BrickData);
00051 if (other_brick->confidence <= 0)
00052 return;
00053
00054
00055
00056
00057 }
00058
00059 bool BrickData::updateParams(const ShapeRoot& other, bool) {
00060 const Shape<BrickData>& other_brick = *static_cast<const Shape<BrickData>*>(&other);
00061
00062 GFL = (GFL*(confidence-1) + other_brick->getGFL())/confidence;
00063 GFR = (GFR*(confidence-1) + other_brick->getGFR())/confidence;
00064 GBL = (GBL*(confidence-1) + other_brick->getGBL())/confidence;
00065 GBR = (GBR*(confidence-1) + other_brick->getGBR())/confidence;
00066 TFL = (TFL*(confidence-1) + other_brick->getTFL())/confidence;
00067 TFR = (TFR*(confidence-1) + other_brick->getTFR())/confidence;
00068 TBL = (TBL*(confidence-1) + other_brick->getTBL())/confidence;
00069 TBR = (TBR*(confidence-1) + other_brick->getTBR())/confidence;
00070 deleteRendering();
00071 return true;
00072 }
00073
00074
00075 void
00076 BrickData::printParams() const {
00077 cout << "Type = " << getTypeName();
00078 cout << "Shape ID = " << getId() << endl;
00079 cout << "Parent ID = " << getParentId() << endl;
00080
00081
00082 cout << endl;
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 printf("color = %d %d %d\n",getColor().red,getColor().green,getColor().blue);
00094 cout << "viewable = " << isViewable() << endl;
00095 }
00096
00097
00098
00099 void BrickData::applyTransform(const NEWMAT::Matrix& Tmat) {
00100 GFL.applyTransform(Tmat);
00101 GFR.applyTransform(Tmat);
00102 GBL.applyTransform(Tmat);
00103 GBR.applyTransform(Tmat);
00104 TFL.applyTransform(Tmat);
00105 TFR.applyTransform(Tmat);
00106 TBL.applyTransform(Tmat);
00107 TBR.applyTransform(Tmat);
00108 }
00109
00110 void BrickData::projectToGround(const NEWMAT::Matrix& camToBase,
00111 const NEWMAT::ColumnVector& groundplane) {
00112 GFL.projectToGround(camToBase,groundplane);
00113 GFR.projectToGround(camToBase,groundplane);
00114 GBL.projectToGround(camToBase,groundplane);
00115 GBR.projectToGround(camToBase,groundplane);
00116
00117
00118 float FLHeight, FRHeight, BRHeight;
00119 TFL.projectToGround(camToBase,groundplane);
00120 TFR.projectToGround(camToBase,groundplane);
00121 TBR.projectToGround(camToBase,groundplane);
00122 FLHeight = TFL.getHeightAbovePoint(GFL, groundplane);
00123 FRHeight = TFR.getHeightAbovePoint(GFR, groundplane);
00124 BRHeight = TBR.getHeightAbovePoint(GBR, groundplane);
00125 float brickHeight = (FLHeight + FRHeight+ BRHeight) / 3.0;
00126 TFL.setCoords(GFL.coordX(), GFL.coordY(), GFL.coordZ() + FLHeight);
00127 TFR.setCoords(GFR.coordX(), GFR.coordY(), GFR.coordZ() + FRHeight);
00128 TBL.setCoords(GBL.coordX(), GBL.coordY(), GBL.coordZ() + brickHeight);
00129 TBR.setCoords(GBR.coordX(), GBR.coordY(), GBR.coordZ() + BRHeight);
00130 centroid = (GFL + GFR + GBL + GBR)/4;
00131 centroid.setCoords(centroid.coordX(), centroid.coordY(), brickHeight/2);
00132 std::cout<<"New centroid: ("<<centroid.coordX()<<","<<centroid.coordY()<<","<<centroid.coordZ()<<")\n";
00133
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 Sketch<bool>* BrickData::render() const {
00146 SketchSpace &renderspace = space->getDualSpace();
00147
00148
00149
00150 Sketch<bool>* draw_result =
00151 new Sketch<bool>(renderspace, "render("+getName()+")");
00152 (*draw_result)->setParentId(getViewableId());
00153 (*draw_result)->setColor(getColor());
00154 *draw_result = 0;
00155 LineData GF(*space, GFL, GFR);
00156 *draw_result = *draw_result & GF.getRendering();
00157 LineData GL(*space, GFL, GBL);
00158 *draw_result = *draw_result & GL.getRendering();
00159 LineData GB(*space, GBL, GBR);
00160 *draw_result = *draw_result & GB.getRendering();
00161 LineData GR(*space, GBR, GFR);
00162 *draw_result = *draw_result & GR.getRendering();
00163
00164 return draw_result;
00165 }
00166
00167
00168
00169
00170
00171
00172 std::vector<Shape<BrickData> > BrickData::findBricks(ShapeSpace& ShS, std::vector<Shape<LineData> > lines)
00173 {
00174 const float lengthConst = .3;
00175 std::vector<Shape<LineData> > resultLines;
00176 std::vector<Shape<BrickData> > resultBricks;
00177 float longLength, shortLength;
00178
00179 if (lines.size() < 3)
00180 {
00181 return resultBricks;
00182 }
00183
00184 lines = stable_sort(lines, not2(LineData::LengthLessThan()));
00185
00186 DO_SHAPEVEC(lines, LineData, l1, {
00187 DO_SHAPENEXT(lines, LineData, l1, l2, {
00188 if (l1->getLength() > l2->getLength()){
00189 longLength = l1->getLength();
00190 shortLength = l2->getLength();
00191 }
00192 else {
00193 longLength = l2->getLength();
00194 shortLength = l1->getLength();
00195 }
00196 if (LineData::ParallelTest()(l1,l2) && !LineData::ColinearTest()(l1,l2) &&
00197 (shortLength / longLength > lengthConst)) {
00198 DO_SHAPENEXT(lines, LineData, l2, l3, {
00199 if (LineData::ParallelTest()(l1,l3) &&
00200 !LineData::ColinearTest()(l1,l3) &&
00201 LineData::ParallelTest()(l2,l3) &&
00202 !LineData::ColinearTest()(l2,l3) &&
00203 (l3->getLength() / longLength > lengthConst) &&
00204 (shortLength / l3->getLength() > lengthConst)) {
00205 NEW_SHAPE_N(l1_2, LineData, new LineData(ShS, l1->leftPt(), l1->rightPt()));
00206 NEW_SHAPE_N(l2_2, LineData, new LineData(ShS, l2->leftPt(), l2->rightPt()));
00207 NEW_SHAPE_N(l3_2, LineData, new LineData(ShS, l3->leftPt(), l3->rightPt()));
00208 l1_2->setParentId(l1->getViewableId());
00209 l2_2->setParentId(l1->getViewableId());
00210 l3_2->setParentId(l1->getViewableId());
00211 resultLines.push_back(l1_2);
00212 resultLines.push_back(l2_2);
00213 resultLines.push_back(l3_2);
00214 }
00215 });
00216 }
00217 });
00218 });
00219
00220 if (resultLines.size() < 3) {
00221 return resultBricks;
00222 }
00223
00224 for (unsigned int i=0; i<resultLines.size(); i+=3)
00225 {
00226 const Shape<LineData>& final1 = ShapeRootTypeConst(resultLines[i+0],LineData);
00227 const Shape<LineData>& final2 = ShapeRootTypeConst(resultLines[i+1],LineData);
00228 const Shape<LineData>& final3 = ShapeRootTypeConst(resultLines[i+2],LineData);
00229
00230
00231
00232
00233
00234 std::vector<Shape<LineData> > threeLines;
00235
00236 if (final1->bottomPt().isBelow(final2->bottomPt(),camcentric))
00237 {
00238 if (final1->bottomPt().isBelow(final3->bottomPt(),camcentric))
00239 {
00240 threeLines.push_back(final1);
00241 if (final2->bottomPt().isBelow(final3->bottomPt(),camcentric))
00242 {
00243 threeLines.push_back(final2);
00244 threeLines.push_back(final3);
00245 }
00246 else
00247 {
00248 threeLines.push_back(final3);
00249 threeLines.push_back(final3);
00250 }
00251 }
00252 else
00253 {
00254 threeLines.push_back(final3);
00255 threeLines.push_back(final1);
00256 threeLines.push_back(final2);
00257 }
00258 }
00259 else
00260 {
00261 if (final2->bottomPt().isBelow(final3->bottomPt(),camcentric))
00262 {
00263 threeLines.push_back(final2);
00264 if (final1->bottomPt().isBelow(final3->bottomPt(),camcentric))
00265 {
00266 threeLines.push_back(final1);
00267 threeLines.push_back(final3);
00268 }
00269 else
00270 {
00271 threeLines.push_back(final3);
00272 threeLines.push_back(final1);
00273 }
00274 }
00275 else
00276 {
00277 threeLines.push_back(final3);
00278 threeLines.push_back(final2);
00279 threeLines.push_back(final1);
00280 }
00281 }
00282 const Shape<LineData> &bottom = ShapeRootTypeConst(threeLines[0], LineData);
00283 const Shape<LineData> &mid = ShapeRootTypeConst(threeLines[1], LineData);
00284 const Shape<LineData> &top = ShapeRootTypeConst(threeLines[2], LineData);
00285
00286
00287
00288
00289
00290
00291 Point gbl(top->leftPt()+(bottom->leftPt() - mid->leftPt()));
00292 Point gbr(top->rightPt()+(bottom->rightPt() - mid->rightPt()));
00293 Shape<BrickData> newBrick (ShS, (Point&)(bottom->leftPt()), (Point&)bottom->rightPt(),
00294 gbl, gbr,
00295 (Point&)mid->leftPt(), (Point&)mid->rightPt(),
00296 (Point&)top->leftPt(), (Point&)top->rightPt());
00297
00298 newBrick->setParentId(final1->getViewableId());
00299
00300 NEW_SHAPE(brickl1, LineData, Shape<LineData>(bottom.getData()));
00301 NEW_SHAPE(brickl2, LineData, Shape<LineData>(mid.getData()));
00302 NEW_SHAPE(brickl3, LineData, Shape<LineData>(top.getData()));
00303
00304 brickl1->setParentId(newBrick->getViewableId());
00305 brickl2->setParentId(newBrick->getViewableId());
00306 brickl3->setParentId(newBrick->getViewableId());
00307
00308 resultBricks.push_back(newBrick);
00309 }
00310
00311 return resultBricks;
00312 }
00313
00314
00315
00316
00317
00318
00319 std::vector<Shape<BrickData> > BrickData::findBricksFromBlobs(ShapeSpace& ShS,
00320 std::vector<Shape<BlobData> > blobs1,
00321 std::vector<Shape<BlobData> > blobs2,
00322 std::vector<Shape<BlobData> > blobs3)
00323 {
00324
00325 const float distanceThresh = 10;
00326
00327 unsigned int i, i1, i2;
00328 Shape<BlobData> blob1, blob2, blob3;
00329
00330 std::vector<Shape<BrickData> > resultBricks;
00331
00332 Point GFL, GFR, GBL, GBR, TFL, TFR, TBL, TBR;
00333 Point c12,c13,c23;
00334
00335 std::vector<std::vector<Point> > corners1;
00336 std::vector<std::vector<Point> > corners2;
00337 std::vector<std::vector<Point> > corners3;
00338 std::vector<bool> used1;
00339 std::vector<bool> used2;
00340 std::vector<bool> used3;
00341 for (i=0; i<blobs1.size(); i++) {
00342 used1.push_back(false);
00343 corners1.push_back(blobs1[i]->findCornersDiagonal());
00344 }
00345 for (i=0; i<blobs2.size(); i++) {
00346 used2.push_back(false);
00347 corners2.push_back(blobs2[i]->findCornersDiagonal());
00348 }
00349 for (i=0; i<blobs3.size(); i++) {
00350 used3.push_back(false);
00351 corners3.push_back(blobs3[i]->findCornersDiagonal());
00352 }
00353
00354
00355 int used;
00356 for (i1=0; i1<blobs1.size(); i1++){
00357 for (i2=0; i2<blobs2.size();i2++){
00358 if (!used1[i1] && !used2[i2]) {
00359 used = addBrickWithTwoSides(ShS, corners1[i1], corners2[i2], corners3,
00360 resultBricks, distanceThresh);
00361 if (used>=0) {
00362 used1[i1] = true;
00363 used2[i2] = true;
00364 used3[used] = true;
00365 resultBricks[resultBricks.size()-1]->setParentId(blobs1[i1]->getViewableId());
00366 }
00367 }
00368 }
00369 }
00370
00371 for (i1=0; i1<blobs1.size(); i1++){
00372 for (i2=0; i2<blobs3.size();i2++){
00373 if (!used1[i1] && !used3[i2]) {
00374 used = addBrickWithTwoSides(ShS, corners1[i1], corners3[i2], corners2,
00375 resultBricks, distanceThresh);
00376 if (used>=0) {
00377 used1[i1] = true;
00378 used3[i2] = true;
00379 used2[used] = true;
00380 resultBricks[resultBricks.size()-1]->setParentId(blobs1[i1]->getViewableId());
00381 }
00382 }
00383 }
00384 }
00385
00386 for (i1=0; i1<blobs3.size(); i1++){
00387 for (i2=0; i2<blobs2.size();i2++){
00388 if (!used3[i1] && !used2[i2]) {
00389 used = addBrickWithTwoSides(ShS, corners3[i1], corners2[i2], corners1,
00390 resultBricks, distanceThresh);
00391 if (used>=0) {
00392 used3[i1] = true;
00393 used2[i2] = true;
00394 used1[used] = true;
00395 resultBricks[resultBricks.size()-1]->setParentId(blobs3[i1]->getViewableId());
00396 }
00397 }
00398 }
00399 }
00400
00401
00402 return resultBricks;
00403 }
00404
00405
00406
00407
00408
00409
00410
00411
00412 int BrickData::addBrickWithTwoSides(ShapeSpace &ShS,
00413 std::vector<Point>& corners1,
00414 std::vector<Point>& corners2,
00415 std::vector<std::vector<Point> >& blobs3,
00416 std::vector<Shape<BrickData> >& result,
00417 float distanceThresh)
00418 {
00419 unsigned int blobi;
00420 int i1=-1,j1=-1, i2=-1, j2=-1;
00421 for (int i=0; i<4 && i2<0; i++) {
00422 for (int j=0; j<4 && j2<0; j++) {
00423 if (corners1[i].distanceFrom(corners2[j]) < distanceThresh) {
00424 if (corners1[(i+1)%4].distanceFrom(corners2[(j+3)%4]) < distanceThresh) {
00425 i1 = i;
00426 i2 = (i+1)%4;
00427 j1 = (j+3)%4;
00428 j2 = j;
00429 }
00430 else if (corners1[(i+3)%4].distanceFrom(corners2[(j+1)%4]) < distanceThresh) {
00431 i1 = (i+3)%4;
00432 i2 = i;
00433 j1 = j;
00434 j2 = (j+1)%4;
00435 }
00436 if (i2>=0) {
00437
00438
00439 bool found = false;
00440 Point center, mid1, mid2, mid3, c1, c2, c3;
00441 for (blobi=0; blobi<blobs3.size() && !found; blobi++) {
00442 for(int k=0; k<4 && !found; k++) {
00443 if (((blobs3[blobi][k].distanceFrom(corners1[i1]) < distanceThresh) +
00444 (blobs3[blobi][(k+1)%4].distanceFrom(corners1[(i1+3)%4]) < distanceThresh) +
00445 (blobs3[blobi][(k+3)%4].distanceFrom(corners2[(j2+1)%4]) < distanceThresh)) > 1) {
00446
00447 found = true;
00448 mid1 = (corners1[i2]+corners2[j1])/2;
00449 if (blobs3[blobi][k].distanceFrom(corners1[i1]) < distanceThresh)
00450 center = (corners1[i1]+corners2[j2]+blobs3[blobi][k])/3;
00451 else
00452 center = (corners1[i1]+corners2[j2])/2;
00453 if (blobs3[blobi][(k+1)%4].distanceFrom(corners1[(i1+3)%4]) < distanceThresh)
00454 mid2 = (blobs3[blobi][(k+1)%4] + corners1[(i1+3)%4])/2;
00455 else
00456 mid2 = corners1[(i1+3)%4];
00457 if (blobs3[blobi][(k+3)%4].distanceFrom(corners2[(j2+1)%4]) < distanceThresh)
00458 mid3 = (blobs3[blobi][(k+3)%4] + corners2[(j2+1)%4])/2;
00459 else
00460 mid3 = corners2[(j2+1)%4];
00461 c1 = corners1[(i1+2)%4];
00462 c2 = blobs3[blobi][(k+2)%4];
00463 c3 = corners2[(j2+2)%4];
00464 }
00465 else if (((blobs3[blobi][k].distanceFrom(corners1[i2]) < distanceThresh) +
00466 (blobs3[blobi][(k+1)%4].distanceFrom(corners2[(j1+3)%4]) < distanceThresh) +
00467 (blobs3[blobi][(k+3)%4].distanceFrom(corners1[(i2+1)%4]) < distanceThresh)) > 1) {
00468
00469 found = true;
00470 mid1 = (corners1[i1]+corners2[j2])/2;
00471 if (blobs3[blobi][k].distanceFrom(corners1[i2]) < distanceThresh)
00472 center = (corners1[i2]+corners2[j1]+blobs3[blobi][k])/3;
00473 else
00474 center = (corners1[i2]+corners2[j1])/2;
00475 if (blobs3[blobi][(k+1)%4].distanceFrom(corners2[(j1+3)%4]) < distanceThresh)
00476 mid2 = (blobs3[blobi][(k+1)%4] + corners2[(j1+3)%4])/2;
00477 else
00478 mid2 = corners2[(j1+3)%4];
00479 if (blobs3[blobi][(k+3)%4].distanceFrom(corners1[(i2+1)%4]) < distanceThresh)
00480 mid3 = (blobs3[blobi][(k+3)%4] + corners1[(i2+1)%4])/2;
00481 else
00482 mid3 = corners1[(i2+1)%4];
00483 c1 = corners2[(j1+2)%4];
00484 c2 = blobs3[blobi][(k+2)%4];
00485 c3 = corners1[(i2+2)%4];
00486 }
00487 }
00488
00489 }
00490
00491 if (found) {
00492
00493
00494
00495 NEW_SHAPE(centerp, PointData, new PointData(ShS, center));
00496 NEW_SHAPE(mid1p, PointData, new PointData(ShS, mid1));
00497 NEW_SHAPE(mid2p, PointData, new PointData(ShS, mid2));
00498 NEW_SHAPE(mid3p, PointData, new PointData(ShS, mid3));
00499 NEW_SHAPE(c1p, PointData, new PointData(ShS, c1));
00500 NEW_SHAPE(c2p, PointData, new PointData(ShS, c2));
00501 NEW_SHAPE(c3p, PointData, new PointData(ShS, c3));
00502 centerp->setColor(rgb(150,0,255));
00503 mid1p->setColor(rgb(150,0,255));
00504 mid2p->setColor(rgb(150,0,255));
00505 mid3p->setColor(rgb(150,0,255));
00506 c1p->setColor(rgb(150,0,255));
00507 c2p->setColor(rgb(150,0,255));
00508 c3p->setColor(rgb(150,0,255));
00509
00510 Point GFL, GFR, GBL, GBR, TFL, TFR, TBL, TBR;
00511
00512 TFR = center;
00513 if (mid1.isBelow(center, camcentric) && mid1.isBelow(mid2, camcentric) && mid1.isBelow(mid3, camcentric)) {
00514 GFR = mid1;
00515 GBR = c1;
00516 if (mid2.isRightOf(mid3, camcentric)) {
00517 TBR = mid2;
00518 TBL = c2;
00519 TFL = mid3;
00520 GFL = c3;
00521 }
00522 else {
00523 TBR = mid3;
00524 TBL = c3;
00525 TFL = mid2;
00526 GFL = c2;
00527 }
00528 }
00529 else if (mid2.isBelow(center, camcentric) && mid2.isBelow(mid1, camcentric) && mid2.isBelow(mid3, camcentric)) {
00530 GFR = mid2;
00531 GBR = c2;
00532 if (mid1.isRightOf(mid3, camcentric)) {
00533 TBR = mid1;
00534 TBL = c1;
00535 TFL = mid3;
00536 GFL = c3;
00537 }
00538 else {
00539 TBR = mid3;
00540 TBL = c3;
00541 TFL = mid1;
00542 GFL = c1;
00543 }
00544 }
00545 else {
00546 GFR = mid3;
00547 GBR = c3;
00548 if (mid2.isRightOf(mid1, camcentric)) {
00549 TBR = mid2;
00550 TBL = c2;
00551 TFL = mid1;
00552 GFL = c1;
00553 }
00554 else {
00555 TBR = mid1;
00556 TBL = c1;
00557 TFL = mid2;
00558 GFL = c2;
00559 }
00560 }
00561
00562 GBL = GFL + (TBL - TFL);
00563
00564 Shape<BrickData> newBrick(ShS, GFL, GFR, GBL, GBR, TFL, TFR, TBL, TBR);
00565 result.push_back(newBrick);
00566 centerp->setParentId(newBrick->getViewableId());
00567 mid1p->setParentId(newBrick->getViewableId());
00568 mid2p->setParentId(newBrick->getViewableId());
00569 mid3p->setParentId(newBrick->getViewableId());
00570 c1p->setParentId(newBrick->getViewableId());
00571 c2p->setParentId(newBrick->getViewableId());
00572 c3p->setParentId(newBrick->getViewableId());
00573 return blobi;
00574 }
00575 else {
00576
00577 }
00578
00579 }
00580 }
00581 }
00582 }
00583
00584 return -1;
00585
00586 }
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609 Shape<BrickData> BrickData::extractBrick(ShapeSpace& space, vector<Shape<BlobData> > &blobs)
00610 {
00611 unsigned int nblobs = blobs.size();
00612 std::vector<Point> centroids;
00613
00614 ShapeRoot invalid;
00615 if (nblobs > 3 || nblobs < 2) {
00616 return ShapeRootType(invalid,BrickData);
00617 }
00618
00619 for (unsigned int i=0; i<nblobs; i++) {
00620 centroids.push_back(blobs[i]->getCentroid());
00621 }
00622
00623
00624
00625 for (unsigned int i=0; i<nblobs; i++) {
00626 for (unsigned int j=i+1; j<nblobs; j++) {
00627 if (centroids[i].distanceFrom(centroids[j]) >=
00628 blobs[i]->topLeft.distanceFrom(centroids[i]) +
00629 blobs[j]->topLeft.distanceFrom(centroids[j])){
00630 return ShapeRootType(invalid,BrickData);
00631 }
00632 }
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642 int top=-1, left=-1, right=-1;
00643
00644 if (centroids[0].isAbove(centroids[1], camcentric)) {
00645 top = 0;
00646 }
00647 else {
00648 top = 1;
00649 }
00650 if (nblobs > 2 && centroids[2].isAbove(centroids[top], camcentric)) {
00651 top = 2;
00652 }
00653
00654 if ((top != 0 && centroids[0].isLeftOf(centroids[1], camcentric)) || top == 1) {
00655 left = 0;
00656 }
00657 else {
00658 left = 1;
00659 }
00660 if (nblobs>2 && top != 2 && centroids[2].isLeftOf(centroids[left], camcentric)) {
00661 left = 2;
00662 }
00663
00664 if (nblobs > 2) {
00665 if (top != 0 && left != 0) {
00666 right = 0;
00667 }
00668 else if (top != 1 && left != 1) {
00669 right = 1;
00670 }
00671 else {
00672 right = 2;
00673 }
00674 }
00675
00676 if (top == left || top == right || left == right){
00677 std::cout<<"ERROR: Brick side misclassification!"<<std::endl;
00678 return ShapeRootType(invalid,BrickData);
00679 }
00680
00681
00682
00683
00684
00685 const int INTERSECT_DIST = 5, MIN_REQUIRED_DIST = 2;
00686 std::vector<Sketch<bool> > boundaries;
00687 NEW_SKETCH_N(topEdist, uchar, visops::edist(blobs[top]->getRendering()));
00688 NEW_SKETCH_N(leftEdist, uchar, visops::edist(blobs[left]->getRendering()));
00689 NEW_SKETCH(tlsmall, bool, topEdist<MIN_REQUIRED_DIST & leftEdist<MIN_REQUIRED_DIST);
00690 if (!tlsmall->max()){
00691 return ShapeRootType(invalid,BrickData);
00692 }
00693 NEW_SKETCH(tl, bool, topEdist<INTERSECT_DIST & leftEdist<INTERSECT_DIST);
00694 rgb green_rgb(0,0,255);
00695 tl->setColor(green_rgb);
00696 boundaries.push_back(tl);
00697
00698 if (nblobs>2) {
00699 NEW_SKETCH_N(rightEdist, uchar, visops::edist(blobs[right]->getRendering()));
00700 NEW_SKETCH(trsmall, bool, topEdist<MIN_REQUIRED_DIST & rightEdist<MIN_REQUIRED_DIST);
00701 if (!trsmall->max()){
00702 return ShapeRootType(invalid,BrickData);
00703 }
00704 NEW_SKETCH(tr, bool, topEdist<INTERSECT_DIST & rightEdist<INTERSECT_DIST);
00705 tr->setColor(green_rgb);
00706 boundaries.push_back(tr);
00707
00708 NEW_SKETCH(lrsmall, bool, leftEdist<MIN_REQUIRED_DIST & rightEdist<MIN_REQUIRED_DIST);
00709 if (!lrsmall->max()){
00710 return ShapeRootType(invalid,BrickData);
00711 }
00712 NEW_SKETCH(lr, bool, leftEdist<INTERSECT_DIST & rightEdist<INTERSECT_DIST);
00713 lr->setColor(green_rgb);
00714 boundaries.push_back(lr);
00715 }
00716
00717
00718
00719
00720
00721 std::vector<std::vector<Point> > points(8);
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 NEW_SHAPE(tlline, LineData, LineData::extractLine(boundaries[0]));
00737 Shape<LineData> trline, lrline;
00738
00739 if (right!=-1) {
00740 trline = LineData::extractLine(boundaries[1]);
00741 lrline = LineData::extractLine(boundaries[2]);
00742
00743
00744 bool on1=false, on2=false;
00745 if (tlline.isValid() && trline.isValid()) {
00746 Point isectPt = tlline->intersectionWithLine(trline, on1, on2);
00747 if (on1) {
00748 tlline->rightPt().setCoords(isectPt);
00749 }
00750 if (on2) {
00751 trline->leftPt().setCoords(isectPt);
00752 }
00753 }
00754
00755 if (tlline.isValid() && lrline.isValid()) {
00756 Point isectPt = tlline->intersectionWithLine(lrline, on1, on2);
00757 if (on1) {
00758 tlline->rightPt().setCoords(isectPt);
00759 }
00760 if (on2) {
00761 lrline->topPt().setCoords(isectPt);
00762 }
00763 }
00764
00765 if (trline.isValid() && lrline.isValid()) {
00766 Point isectPt = trline->intersectionWithLine(lrline, on1, on2);
00767 if (on1) {
00768 trline->leftPt().setCoords(isectPt);
00769 }
00770 if (on2) {
00771 lrline->topPt().setCoords(isectPt);
00772 }
00773 }
00774
00775
00776 if (trline.isValid()) {
00777 points[2].push_back(trline->leftPt());
00778 points[6].push_back(trline->rightPt());
00779 }
00780
00781 if (lrline.isValid()) {
00782 points[2].push_back(lrline->topPt());
00783 points[3].push_back(lrline->bottomPt());
00784 }
00785 }
00786
00787 if (tlline.isValid()) {
00788 points[1].push_back(tlline->leftPt());
00789 points[2].push_back(tlline->rightPt());
00790 }
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801 std::vector<Point> candidates;
00802
00803
00804
00805
00806 if (tlline.isValid()) {
00807 if (trline.isValid() && trline->getLength() > tlline->getLength()) {
00808 candidates = findOrthogonalBoundingBox(space, blobs[top], centroids[top], trline);
00809 }
00810 else {
00811 candidates = findOrthogonalBoundingBox(space, blobs[top], centroids[top], tlline);
00812 }
00813 }
00814 else if (trline.isValid()) {
00815 candidates = findOrthogonalBoundingBox(space, blobs[top], centroids[top], trline);
00816 }
00817
00818 float cornerValue;
00819
00820 std::vector<Point> tcorners = blobs[top]->findCorners(4, candidates, cornerValue);
00821
00822 if (tcorners.size() == 4) {
00823
00824
00825
00826
00827 unsigned int leftCorner = 0;
00828 for (unsigned int i=1; i<4; i++){
00829 if (tcorners[i].isLeftOf(tcorners[leftCorner], camcentric)) {
00830 leftCorner = i;
00831 }
00832 }
00833 int closeCorner = -1;
00834 float mostLeft = tcorners[leftCorner].coordX();
00835 const int MAX_CLOSE_DIST = 5;
00836 for (unsigned int i=0; i<4; i++) {
00837 if (i != leftCorner && tcorners[i].coordX() - mostLeft < MAX_CLOSE_DIST) {
00838 closeCorner = i;
00839 }
00840 }
00841
00842 if (closeCorner != -1) {
00843
00844 if ((unsigned int)closeCorner == (leftCorner+1)%4) {
00845 leftCorner = closeCorner;
00846 }
00847 else if ((unsigned int)closeCorner != (leftCorner+3)%4) {
00848 std::cout<<"WARNING, opposite corners are close together!"<<std::endl;
00849 }
00850 }
00851 NEW_SHAPE(top1, PointData, PointData(space, tcorners[leftCorner]));
00852 points[1].push_back(tcorners[leftCorner]);
00853 points[2].push_back(tcorners[(leftCorner+1)%4]);
00854 points[6].push_back(tcorners[(leftCorner+2)%4]);
00855 points[5].push_back(tcorners[(leftCorner+3)%4]);
00856
00857 }
00858 else {
00859
00860
00861 }
00862
00863
00864
00865
00866 candidates.clear();
00867 if (tlline.isValid()) {
00868 if (lrline.isValid() && lrline->getLength() > tlline->getLength()) {
00869 candidates = findOrthogonalBoundingBox(space, blobs[left], centroids[left], lrline);
00870 }
00871 else {
00872 candidates = findOrthogonalBoundingBox(space, blobs[left], centroids[left], tlline);
00873 }
00874 }
00875 else if (trline.isValid()) {
00876 candidates = findOrthogonalBoundingBox(space, blobs[left], centroids[left], lrline);
00877 }
00878
00879 for (unsigned int i=0; i<candidates.size(); i++) {
00880 NEW_SHAPE(candidate, PointData, PointData(space, candidates[i]));
00881 candidate->setParentId(blobs[left]->getViewableId());
00882 }
00883 std::vector<Point> lcorners = blobs[left]->findCorners(4, candidates, cornerValue);
00884 if (lcorners.size() == 4) {
00885
00886
00887
00888 unsigned int rightCorner = 0;
00889 for (unsigned int i=1; i<4; i++){
00890 if (lcorners[i].isRightOf(lcorners[rightCorner], camcentric)) {
00891 rightCorner = i;
00892 }
00893 }
00894 int closeCorner = -1;
00895 float mostRight = lcorners[rightCorner].coordX();
00896 const int MAX_CLOSE_DIST = 5;
00897 for (unsigned int i=0; i<4; i++) {
00898 if (i != rightCorner && mostRight - lcorners[i].coordX() < MAX_CLOSE_DIST) {
00899 closeCorner = i;
00900 }
00901 }
00902
00903 if (closeCorner != -1) {
00904
00905 if ((unsigned int)closeCorner == (rightCorner+3)%4) {
00906 rightCorner = closeCorner;
00907 }
00908 else if ((unsigned int)closeCorner != (rightCorner+1)%4) {
00909 std::cout<<"WARNING, opposite corners are close together!"<<std::endl;
00910 }
00911 }
00912 NEW_SHAPE(left2, PointData, PointData(space, lcorners[rightCorner]));
00913 points[3].push_back(lcorners[rightCorner]);
00914 points[2].push_back(lcorners[(rightCorner+1)%4]);
00915 points[1].push_back(lcorners[(rightCorner+2)%4]);
00916 points[0].push_back(lcorners[(rightCorner+3)%4]);
00917
00918 }
00919 else {
00920
00921 }
00922
00923
00924 if (right != -1) {
00925
00926 candidates.clear();
00927 if (trline.isValid()) {
00928 if (lrline.isValid() && lrline->getLength() > trline->getLength()) {
00929 candidates = findOrthogonalBoundingBox(space, blobs[right], centroids[right], lrline);
00930 }
00931 else {
00932 candidates = findOrthogonalBoundingBox(space, blobs[right], centroids[right], trline);
00933 }
00934 }
00935 else if (lrline.isValid()) {
00936 candidates = findOrthogonalBoundingBox(space, blobs[right], centroids[right], lrline);
00937 }
00938
00939 std::vector<Point> rcorners = blobs[right]->findCorners(4, candidates, cornerValue);
00940 if (rcorners.size() == 4) {
00941
00942
00943
00944 unsigned int bottomCorner = 0;
00945 for (unsigned int i=1; i<4; i++){
00946 if (rcorners[i].isBelow(rcorners[bottomCorner], camcentric)) {
00947 bottomCorner = i;
00948 }
00949 }
00950 int closeCorner = -1;
00951 float mostBottom = rcorners[bottomCorner].coordY();
00952 const int MAX_CLOSE_DIST = 5;
00953 for (unsigned int i=0; i<4; i++) {
00954 if (i != bottomCorner && mostBottom - rcorners[i].coordY() < MAX_CLOSE_DIST) {
00955 closeCorner = i;
00956 }
00957 }
00958
00959 if (closeCorner != -1) {
00960
00961 if ((unsigned int)closeCorner == (bottomCorner+3)%4) {
00962 bottomCorner = closeCorner;
00963 }
00964 else if ((unsigned int)closeCorner != (bottomCorner+1)%4) {
00965 std::cout<<"WARNING, opposite corners are close together!"<<std::endl;
00966 }
00967 }
00968 NEW_SHAPE(right3, PointData, PointData(space,rcorners[bottomCorner]));
00969 points[3].push_back(rcorners[bottomCorner]);
00970 points[7].push_back(rcorners[(bottomCorner+1)%4]);
00971 points[6].push_back(rcorners[(bottomCorner+2)%4]);
00972 points[2].push_back(rcorners[(bottomCorner+3)%4]);
00973
00974 }
00975 }
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995 vector<Point> finalCorners(8);
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005 if (points[2].size()==0 || points[1].size()==0){
01006 return ShapeRootType(invalid,BrickData);
01007 }
01008
01009 Point empty(0,0);
01010
01011
01012
01013
01014 for (unsigned int i=0; i<8; i++) {
01015 finalCorners[i] = empty;
01016 for (unsigned int j=0; j<points[i].size(); j++) {
01017 finalCorners[i]+=points[i][j];
01018 }
01019 if (points[i].size() > 0) {
01020 finalCorners[i]/=points[i].size();
01021 }
01022 }
01023
01024 if (points[3].size()==0){
01025
01026 return ShapeRootType(invalid,BrickData);
01027 }
01028
01029 if (points[6].size() == 0) {
01030
01031 if (tlline.isValid()) {
01032 NEW_SKETCH_N(topRendering, bool, blobs[top]->getRendering());
01033 Point topPt = (Region::extractRegion(topRendering)).mostDistantPtFrom(tlline.getData());
01034 NEW_SHAPE(intersectLine, LineData, LineData(space, topPt, tlline->getThetaNorm()));
01035 Point intersectPoint = intersectLine->intersectionWithLine(tlline);
01036
01037 finalCorners[6] = topPt+finalCorners[2]-intersectPoint;
01038 }
01039
01040 else {
01041 return ShapeRootType(invalid,BrickData);
01042 }
01043 }
01044
01045 if (points[0].size() == 0) {
01046 finalCorners[0] = finalCorners[3] + finalCorners[1]-finalCorners[2];
01047 }
01048
01049 if (points[5].size() == 0) {
01050 finalCorners[5] = finalCorners[6] + finalCorners[1]-finalCorners[2];
01051 }
01052
01053 if (points[7].size() == 0) {
01054 finalCorners[7] = finalCorners[3] + finalCorners[6]-finalCorners[2];
01055 }
01056
01057 finalCorners[4] = finalCorners[5] + finalCorners[7] - finalCorners[6] +
01058 finalCorners[5] + finalCorners[0] - finalCorners[1] +
01059 finalCorners[0] + finalCorners[7] - finalCorners[3];
01060 finalCorners[4]/=3.0;
01061
01062
01063 NEW_SHAPE(returnbrick, BrickData, new BrickData(space,
01064 finalCorners[0], finalCorners[3],
01065 finalCorners[4], finalCorners[7],
01066 finalCorners[1], finalCorners[2],
01067 finalCorners[5], finalCorners[6]));
01068 return returnbrick;
01069
01070 }
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080 vector<Point> BrickData::findOrthogonalBoundingBox(ShapeSpace& space, Shape<BlobData> blob, Point centroid, Shape<LineData> parallel)
01081 {
01082 const float PARALLEL_EXTEND_FACTOR = .6, ORTHO_EXTEND_FACTOR = .6;
01083
01084 vector<Point> candidates;
01085 LineData candidate1(space, parallel->end1Pt(), parallel->end2Pt());
01086
01087
01088 Point parallelExtend(candidate1.end2Pt() - candidate1.end1Pt());
01089 parallelExtend *= PARALLEL_EXTEND_FACTOR;
01090 LineData ortho(space, centroid, candidate1.getThetaNorm());
01091 Point orthoIsect = candidate1.intersectionWithLine(ortho);
01092 Point candidate2Offset = (centroid - orthoIsect) * 2.0;
01093 Point orthoExtend = candidate2Offset * ORTHO_EXTEND_FACTOR;
01094
01095 LineData candidate2(space, candidate1.end1Pt() + candidate2Offset + orthoExtend - parallelExtend,
01096 candidate1.end2Pt() + candidate2Offset + orthoExtend + parallelExtend);
01097 candidate1.setEndPts(candidate1.end1Pt() - orthoExtend - parallelExtend,
01098 candidate1.end2Pt() - orthoExtend + parallelExtend);
01099 candidates.push_back(candidate1.leftPt());
01100 candidates.push_back(candidate1.rightPt());
01101 candidates.push_back(candidate2.rightPt());
01102 candidates.push_back(candidate2.leftPt());
01103
01104
01105 for (unsigned int i=0; i<candidates.size(); i++) {
01106 NEW_SHAPE_N(candidate, PointData, PointData(space, candidates[i]));
01107 candidate->setParentId(blob->getViewableId());
01108 }
01109
01110
01111 Point centerPoint = (candidates[0] + candidates[1] + candidates[2] + candidates[3]) / 4.0;
01112 vector<float> centerAngles;
01113 for (unsigned int i=0; i<candidates.size(); i++) {
01114 NEW_SHAPE_N(centerLine, LineData, LineData(space, centerPoint, candidates[i]));
01115 centerLine->setParentId(blob->getViewableId());
01116 centerAngles.push_back(atan2(centerLine->end2Pt().coordY() - centerLine->end1Pt().coordY(),
01117 centerLine->end2Pt().coordX() - centerLine->end1Pt().coordX()));
01118 }
01119
01120
01121 vector<Point> orderedPoints;
01122
01123 int maxi = 0, mini = 0;
01124 float maxAng = centerAngles[0];
01125 float minAng = maxAng;
01126
01127 for (unsigned int i=1; i<candidates.size(); i++) {
01128 if (centerAngles[i] > maxAng) {
01129 maxAng = centerAngles[i];
01130 maxi = i;
01131 }
01132 if (centerAngles[i] < minAng) {
01133 minAng = centerAngles[i];
01134 mini = i;
01135 }
01136
01137 }
01138
01139 orderedPoints.push_back(candidates[maxi]);
01140
01141 float lastMax = maxAng;
01142 for (unsigned int i=1; i<candidates.size(); i++) {
01143 maxi = mini;
01144 maxAng = minAng;
01145 for (unsigned int j=0; j<candidates.size(); j++) {
01146 float curAng = centerAngles[j];
01147 if (curAng > maxAng && curAng < lastMax) {
01148 maxi = j;
01149 maxAng = curAng;
01150 }
01151 }
01152 orderedPoints.push_back(candidates[maxi]);
01153 lastMax = maxAng;
01154 }
01155
01156
01157 for (unsigned int i=0; i<candidates.size(); i++) {
01158 NEW_SHAPE(orderedcandidate, PointData, PointData(space, orderedPoints[i]));
01159 orderedcandidate->setParentId(blob->getViewableId());
01160 }
01161
01162 return orderedPoints;
01163 }
01164
01165
01166
01167 }