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