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