00001 #include <DualCoding/CylinderData.h>
00002 #include <DualCoding/ShapeCylinder.h>
00003 #include "SketchSpace.h"
00004 #include "Sketch.h"
00005 #include "ShapeSpace.h"
00006 #include "ShapeRoot.h"
00007
00008 #include "ShapeBlob.h"
00009 using namespace std;
00010
00011 namespace DualCoding {
00012
00013 DATASTUFF_CC(CylinderData);
00014
00015 CylinderData::CylinderData(ShapeSpace& _space, Point _centroid, float _height, float _radius, fmat::Quaternion _orientation) :
00016 BaseData(_space, getStaticType()), centroid(_centroid), height(_height), radius(_radius), orientation(_orientation) {
00017 centroid.setRefFrameType(getRefFrameType());
00018 mobile = true;
00019 }
00020
00021 bool CylinderData::isMatchFor(const ShapeRoot& other) const {
00022 if (!(isSameTypeAs(other) && isSameColorAs(other)))
00023 return false;
00024
00025 const Shape<CylinderData>& otherCyl = ShapeRootTypeConst(other,CylinderData);
00026
00027 float diff = (centroid - otherCyl->centroid).xyzNorm();
00028
00029 if (diff < 3*radius && fabs(radius - otherCyl->radius) < radius*0.8)
00030 return true;
00031 else
00032 return false;
00033 }
00034
00035
00036 Point CylinderData::getCentroid() const { return centroid; }
00037
00038 bool CylinderData::updateParams(const ShapeRoot&, bool) { return true; }
00039
00040 BoundingBox2D CylinderData::getBoundingBox() const {
00041 BoundingBox2D b;
00042 b.expand(fmat::pack(centroid.coordX()-radius, centroid.coordY()+height/2));
00043 b.expand(fmat::pack(centroid.coordX()+radius, centroid.coordY()-height/2));
00044 return b;
00045 }
00046
00047 void CylinderData::printParams() const {
00048 cout << "Type = " << getTypeName() << " ID=" << getId() << " ParentID=" << getParentId() << endl;
00049 printf(" color = %d %d %d\n",getColor().red,getColor().green,getColor().blue);
00050 cout << " centroid = " << centroid << endl;
00051 cout << " radius = " << radius << endl;
00052 cout << " height = " << height << endl;
00053 cout << " orientation = " << orientation << endl;
00054 }
00055
00056 void CylinderData::applyTransform(const fmat::Transform& Tmat, const ReferenceFrameType_t newref) {
00057 centroid.applyTransform(Tmat,newref);
00058 }
00059
00060 void CylinderData::projectToGround(const fmat::Transform& camToBase, const PlaneEquation& groundplane) {
00061 float camRadius = radius;
00062 float camHeight = height;
00063 float assumedHalfHeight = centroid.coordZ();
00064 Point bottomCenterPt = Point (centroid.coordX(), centroid.coordY()+height/2, 0, camcentric);
00065 Point bottomLeftPt = Point (centroid.coordX()-radius, centroid.coordY()+height/2, 0, camcentric);
00066 bottomLeftPt.projectToGround(camToBase,groundplane);
00067 bottomCenterPt.projectToGround(camToBase,groundplane);
00068 float diff = (bottomCenterPt - bottomLeftPt).xyNorm();
00069 radius = diff;
00070 float theta = std::atan2(bottomCenterPt.coordY(), bottomCenterPt.coordX());
00071 float xcenter = bottomCenterPt.coordX() + radius * cos(theta);
00072 float ycenter = bottomCenterPt.coordY() + radius * sin(theta);
00073 if ( assumedHalfHeight > 0 )
00074 height = assumedHalfHeight * 2;
00075 else
00076 height = radius/camRadius * camHeight;
00077 centroid = Point(xcenter, ycenter, height/2, egocentric);
00078 }
00079
00080 Sketch<bool>* CylinderData::render() const {
00081 SketchSpace &SkS = space->getDualSpace();
00082 Sketch<bool>* result = new Sketch<bool>(SkS, "render("+getName()+")");
00083 *result = false;
00084 const float semimajor = radius;
00085 const float semiminor = semimajor;
00086 fmat::Column<3> ctr;
00087 ctr[0] = getCentroid().coordX();
00088 ctr[1] = getCentroid().coordY();
00089 ctr[2] = getCentroid().coordZ();
00090 SkS.applyTmat(ctr);
00091 const float &cx = ctr[0];
00092 const float &cy = ctr[1];
00093 const fmat::Transform &Tmat = SkS.getTmat();
00094 const float orient = M_PI / 2;
00095 fmat::Column<2> ori;
00096 ori[0] = cos(orient);
00097 ori[1] = sin(orient);
00098 fmat::Matrix<2,2> rot;
00099 rot(0,0) = Tmat(0,0);
00100 rot(0,1) = Tmat(0,1);
00101 rot(1,0) = Tmat(1,0);
00102 rot(1,1) = Tmat(1,1);
00103 ori = rot * ori;
00104 const float &cosT = ori[0];
00105 const float &sinT = ori[1];
00106 const float xRange = semimajor;
00107 const float majorSq = xRange*xRange;
00108 const float mnrDevMjr = semiminor/semimajor;
00109 for (float xDist = -xRange; xDist <= xRange; xDist+=0.2f) {
00110 const float yRange = sqrt(max((float)0, majorSq - xDist*xDist)) * mnrDevMjr;
00111 for (float yDist = -yRange; yDist <= yRange; yDist+=0.2f) {
00112 int const px = round(cx+xDist*cosT-yDist*sinT);
00113 int const py = round(cy+yDist*cosT+xDist*sinT);
00114 if ( px >= 0 && px < result->width &&
00115 py >= 0 && py < result->height )
00116 (*result)(px,py) = true;
00117 }
00118 }
00119 return result;
00120 }
00121
00122 std::vector<Shape<CylinderData> >
00123 CylinderData::extractCylinders(const Sketch<uchar> &sketch,
00124 const std::set<color_index>& colors,
00125 const std::map<color_index,coordinate_t>& assumedHeights,
00126 const std::map<color_index,int>& minCylinderAreas,
00127 int maxcylinders,
00128 std::vector<GazePoint> &addGazePts) {
00129
00130
00131 std::map<color_index, BlobData::BlobOrientation_t> orients;
00132 for (std::map<color_index, BlobData::BlobOrientation_t>::iterator it = orients.begin(); it != orients.end(); ++it) {
00133 it->second = BlobData::pillar;
00134 }
00135
00136 std::vector<Shape<BlobData> > blobs = BlobData::extractBlobs(sketch, colors, minCylinderAreas, orients, assumedHeights, maxcylinders);
00137 std::vector<Shape<CylinderData> > resultingCylinders;
00138
00139 ShapeSpace &shs = sketch->getSpace().getDualSpace();
00140 for (std::vector<Shape<BlobData> >::const_iterator it = blobs.begin(); it != blobs.end(); it++) {
00141 const Shape<BlobData> &blob = *it;
00142 Point centroid = blob->getCentroid();
00143 if ( blob->bottomValid && blob->leftValid && blob->rightValid ) {
00144
00145 float Ydist = blob->bottomLeft.coordY() - blob->topLeft.coordY();
00146 float height = blob->topValid ? Ydist : 0;
00147 float diameter = blob->topRight.coordX() - blob->topLeft.coordX();
00148 float radius = diameter / 2;
00149
00150 if ( blob->getArea() > height*diameter/3 ) {
00151 fmat::Quaternion orientation = fmat::Quaternion();
00152 std::map<color_index,coordinate_t>::const_iterator it_h = assumedHeights.find(ProjectInterface::getColorIndex(blob->getColor()));
00153 coordinate_t assumedHeight = (it_h != assumedHeights.end()) ? it_h->second : 0;
00154 (centroid.getCoords())[2] = assumedHeight/2;
00155 CylinderData *cylinder = new CylinderData(shs, centroid, height, radius, orientation);
00156 cylinder->setColor(blob->getColor());
00157 cylinder->setParentId(blob->getParentId());
00158 resultingCylinders.push_back(Shape<CylinderData>(cylinder));
00159 }
00160 }
00161 else {
00162
00163 addGazePts.push_back(GazePoint(GazePoint::centered,centroid));
00164 }
00165 shs.deleteShape(const_cast<Shape<BlobData>&>(blob));
00166 }
00167 return resultingCylinders;
00168 }
00169
00170 }