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