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 "PyramidData.h"
00018 #include "ShapePyramid.h"
00019 #include "ShapePoint.h"
00020 #include "Region.h"
00021
00022 using namespace std;
00023
00024 namespace DualCoding {
00025
00026 PyramidData::PyramidData(ShapeSpace& _space,
00027 const EndPoint &_FL, const EndPoint &_FR,
00028 const EndPoint &_BL, const EndPoint &_BR,
00029 const EndPoint &_Top)
00030 : BaseData(_space,pyramidDataType),
00031 FL(_FL), FR(_FR), BL(_BL), BR(_BR), Top(_Top),
00032 centroid((FL + FR + BL + BR + Top) / 5)
00033 {
00034 }
00035
00036
00037 DATASTUFF_CC(PyramidData);
00038
00039 bool PyramidData::isMatchFor(const ShapeRoot& other) const {
00040 if (!(isSameTypeAs(other) && isSameColorAs(other)))
00041 return false;
00042
00043
00044 float dist = 0;
00045 return dist < 20;
00046 }
00047
00048 void PyramidData::mergeWith(const ShapeRoot& other) {
00049 const Shape<PyramidData>& other_pyramid = ShapeRootTypeConst(other,PyramidData);
00050 if (other_pyramid->confidence <= 0)
00051 return;
00052 }
00053
00054 bool PyramidData::updateParams(const ShapeRoot& other, bool) {
00055 const Shape<PyramidData>& other_pyramid = *static_cast<const Shape<PyramidData>*>(&other);
00056
00057 FL = (FL*(confidence-1) + other_pyramid->getFL())/confidence;
00058 FR = (FR*(confidence-1) + other_pyramid->getFR())/confidence;
00059 BL = (BL*(confidence-1) + other_pyramid->getBL())/confidence;
00060 BR = (BR*(confidence-1) + other_pyramid->getBR())/confidence;
00061 Top = (Top*(confidence-1) + other_pyramid->getTop())/confidence;
00062 deleteRendering();
00063 return true;
00064 }
00065
00066
00067 void PyramidData::printParams() const {
00068 cout << "Type = " << getTypeName();
00069 cout << "Shape ID = " << getId() << endl;
00070 cout << "Parent ID = " << getParentId() << endl;
00071
00072 printf("color = %d %d %d\n",getColor().red,getColor().green,getColor().blue);
00073 cout << "viewable = " << isViewable() << endl;
00074 }
00075
00076
00077
00078 void PyramidData::applyTransform(const fmat::Transform& Tmat, const ReferenceFrameType_t newref) {
00079 FL.applyTransform(Tmat,newref);
00080 FR.applyTransform(Tmat,newref);
00081 BL.applyTransform(Tmat,newref);
00082 BR.applyTransform(Tmat,newref);
00083 Top.applyTransform(Tmat,newref);
00084 }
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 void PyramidData::projectToGround(const fmat::Transform & camToBase, const PlaneEquation& groundplane) {
00103 FL.projectToGround(camToBase, groundplane);
00104 FR.projectToGround(camToBase, groundplane);
00105 BL.projectToGround(camToBase, groundplane);
00106 BR.projectToGround(camToBase, groundplane);
00107
00108 Point bottomCenter = (FL + FR + BL + BR) / 4.f;
00109 bottomCenter.setRefFrameType(egocentric);
00110 float height;
00111 Top.projectToGround(camToBase, groundplane);
00112 height = Top.getHeightAbovePoint(bottomCenter, groundplane);
00113 Top.setCoords(bottomCenter.coordX(), bottomCenter.coordY(), bottomCenter.coordZ() + height);
00114 centroid = bottomCenter;
00115 centroid.setCoords(centroid.coordX(), centroid.coordY(), centroid.coordZ() + height/5);
00116 std::cout << "New centroid: " << centroid << endl;
00117 }
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 Sketch<bool>* PyramidData::render() const {
00129 SketchSpace &renderspace = space->getDualSpace();
00130
00131
00132
00133 Sketch<bool>* draw_result =
00134 new Sketch<bool>(renderspace, "render("+getName()+")");
00135 (*draw_result)->setParentId(getViewableId());
00136 (*draw_result)->setColor(getColor());
00137 *draw_result = 0;
00138 LineData F(*space, FL, FR);
00139 *draw_result = *draw_result & F.getRendering();
00140 LineData L(*space, FL, BL);
00141 *draw_result = *draw_result & L.getRendering();
00142 LineData B(*space, BL, BR);
00143 *draw_result = *draw_result & B.getRendering();
00144 LineData R(*space, BR, FR);
00145 *draw_result = *draw_result & R.getRendering();
00146 LineData FT(*space, FL, Top);
00147 *draw_result = *draw_result & FT.getRendering();
00148 LineData LT(*space, FR, Top);
00149 *draw_result = *draw_result & LT.getRendering();
00150 LineData BT(*space, BL, Top);
00151 *draw_result = *draw_result & BT.getRendering();
00152 LineData RT(*space, BR, Top);
00153 *draw_result = *draw_result & RT.getRendering();
00154
00155 return draw_result;
00156 }
00157
00158
00159
00160
00161
00162
00163 Shape<PyramidData> PyramidData::extractPyramid(ShapeSpace& space, vector<Shape<BlobData> > &blobs)
00164 {
00165 unsigned int nblobs = blobs.size();
00166 std::vector<Point> centroids;
00167
00168 ShapeRoot invalid;
00169 if (nblobs != 2) {
00170 return ShapeRootType(invalid,PyramidData);
00171 }
00172
00173 for (unsigned int i=0; i<nblobs; i++) {
00174 centroids.push_back(blobs[i]->getCentroid());
00175 }
00176
00177
00178 if (centroids[0].distanceFrom(centroids[1]) >=
00179 blobs[0]->topLeft.distanceFrom(centroids[0]) +
00180 blobs[1]->topLeft.distanceFrom(centroids[1])){
00181 return ShapeRootType(invalid,PyramidData);
00182 }
00183
00184 int left=-1, right=-1;
00185
00186 if (centroids[0].isLeftOf(centroids[1], camcentric)) {
00187 left = 0;
00188 right = 1;
00189 }
00190 else {
00191 left = 1;
00192 right = 0;
00193 }
00194
00195 const int INTERSECT_DIST = 5, MIN_REQUIRED_DIST = 2;
00196 NEW_SKETCH_N(leftEdist, uchar, visops::mdist(blobs[left]->getRendering()));
00197 NEW_SKETCH_N(rightEdist, uchar, visops::mdist(blobs[right]->getRendering()));
00198 NEW_SKETCH(small, bool, (leftEdist<MIN_REQUIRED_DIST) & (rightEdist<MIN_REQUIRED_DIST));
00199 if (!small->max()){
00200 return ShapeRootType(invalid,PyramidData);
00201 }
00202 NEW_SKETCH(boundary, bool, (leftEdist<INTERSECT_DIST) & (rightEdist<INTERSECT_DIST));
00203 rgb green_rgb(0, 255, 0);
00204 boundary->setColor(green_rgb);
00205
00206
00207 std::vector<std::vector<Point> > points(5);
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 NEW_SHAPE(boundaryline, LineData, LineData::extractLine(boundary));
00221
00222 if (boundaryline.isValid()) {
00223 points[0].push_back(boundaryline->topPt());
00224 points[2].push_back(boundaryline->bottomPt());
00225 }
00226
00227
00228
00229
00230
00231
00232 std::vector<Point> candidates;
00233
00234 candidates = findBoundingTriangle(space, blobs[left],
00235 centroids[left], boundaryline);
00236
00237 float cornerValue;
00238
00239 std::vector<Point> lcorners = blobs[left]->findCorners(3, candidates, cornerValue);
00240
00241 if (lcorners.size() == 3) {
00242
00243 unsigned int leftCorner = 0;
00244 for (unsigned int i=1; i<3; i++){
00245 if (lcorners[i].isLeftOf(lcorners[leftCorner], camcentric)) {
00246 leftCorner = i;
00247 }
00248 }
00249
00250 points[1].push_back(lcorners[leftCorner]);
00251 points[2].push_back(lcorners[(leftCorner+1)%3]);
00252 points[0].push_back(lcorners[(leftCorner+2)%3]);
00253
00254 }
00255 else {
00256 return ShapeRootType(invalid,PyramidData);
00257 }
00258
00259
00260
00261
00262 candidates.clear();
00263 candidates = findBoundingTriangle(space, blobs[right],
00264 centroids[right], boundaryline);
00265
00266 std::vector<Point> rcorners = blobs[right]->findCorners(3, candidates, cornerValue);
00267
00268 if (rcorners.size() == 3) {
00269
00270 unsigned int rightCorner = 0;
00271 for (unsigned int i=1; i<3; i++){
00272 if (rcorners[i].isRightOf(rcorners[rightCorner], camcentric)) {
00273 rightCorner = i;
00274 }
00275 }
00276
00277 points[3].push_back(rcorners[rightCorner]);
00278 points[0].push_back(rcorners[(rightCorner+1)%3]);
00279 points[2].push_back(rcorners[(rightCorner+2)%3]);
00280
00281 }
00282 else {
00283 return ShapeRootType(invalid,PyramidData);
00284 }
00285
00286
00287 for (unsigned int i=0; i<5; i++){
00288 for (unsigned int j=0; j<points[i].size(); j++) {
00289 NEW_SHAPE(corner, PointData, PointData(space, points[i][j]));
00290 char name[10];
00291 sprintf(name, "corner%d%d",i,j);
00292 corner->setName(name);
00293 }
00294 }
00295
00296
00297 vector<Point> finalCorners(5);
00298
00299 Point empty(0,0);
00300
00301 for (unsigned int i=0; i<5; i++) {
00302 finalCorners[i] = empty;
00303 for (unsigned int j=0; j<points[i].size(); j++) {
00304 finalCorners[i]+=points[i][j];
00305 }
00306 if (points[i].size() > 0) {
00307 finalCorners[i]/=points[i].size();
00308 }
00309 }
00310
00311
00312
00313
00314 finalCorners[4] = finalCorners[1] + finalCorners[3] - finalCorners[2];
00315
00316
00317 NEW_SHAPE(returnPyramid, PyramidData, new PyramidData(space,
00318 finalCorners[1],
00319 finalCorners[2],
00320 finalCorners[4],
00321 finalCorners[3],
00322 finalCorners[0]));
00323
00324 return returnPyramid;
00325 }
00326
00327
00328
00329
00330
00331 vector<Point> PyramidData::findBoundingTriangle(ShapeSpace& space, Shape<BlobData> blob,
00332 Point , Shape<LineData> parallel)
00333 {
00334
00335 const float PARALLEL_EXTEND_FACTOR = .4f, ORTHO_EXTEND_FACTOR = .4f;
00336
00337 vector<Point> candidates;
00338
00339 Point thirdPoint = (Region::extractRegion(blob->getRendering())).mostDistantPtFrom(parallel.getData());
00340
00341 LineData perpendicular(space, thirdPoint, parallel->getThetaNorm());
00342
00343 Point isect(perpendicular.intersectionWithLine(parallel));
00344
00345 Point orthoExtend((thirdPoint - isect)*ORTHO_EXTEND_FACTOR);
00346 Point parallelExtend((parallel->end2Pt() - parallel->end1Pt())*PARALLEL_EXTEND_FACTOR);
00347
00348 Point pt1(parallel->end1Pt() - parallelExtend - orthoExtend);
00349 Point pt2(parallel->end2Pt() + parallelExtend - orthoExtend);
00350
00351 if ((pt1.isAbove(pt2, camcentric) && thirdPoint.isLeftOf(pt1, camcentric)) ||
00352 (!pt1.isAbove(pt2, camcentric) && !thirdPoint.isLeftOf(pt1, camcentric))){
00353 candidates.push_back(pt2);
00354 candidates.push_back(pt1);
00355 }
00356 else {
00357 candidates.push_back(pt1);
00358 candidates.push_back(pt2);
00359 }
00360 candidates.push_back(thirdPoint + orthoExtend);
00361
00362
00363 NEW_SHAPE(candidate31, PointData, PointData(space, candidates[0]));
00364 NEW_SHAPE(candidate32, PointData, PointData(space, candidates[1]));
00365 NEW_SHAPE(candidate33, PointData, PointData(space, candidates[2]));
00366 candidate31->setParentId(blob->getViewableId());
00367 candidate32->setParentId(blob->getViewableId());
00368 candidate33->setParentId(blob->getViewableId());
00369
00370 return candidates;
00371 }
00372
00373
00374 }