Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

EllipseData.cc

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #include <iostream>
00003 #include <vector>
00004 #include <list>
00005 #include <math.h>
00006 
00007 #include "SketchSpace.h"
00008 #include "Sketch.h"
00009 #include "Region.h"
00010 #include "visops.h"
00011 
00012 #include "ShapeSpace.h"  // required by DATASTUFF_CC
00013 #include "ShapeRoot.h"   // required by DATASTUFF_CC
00014 
00015 #include "EllipseData.h"
00016 #include "ShapeEllipse.h"
00017 
00018 #include "Crew/MapBuilder.h"
00019 #include "VRmixin.h"
00020 
00021 using namespace std;
00022 
00023 namespace DualCoding {
00024 
00025 inline int round(float x) { return (int) ceil((double)x-0.5f); }
00026 
00027 EllipseData::EllipseData(ShapeSpace& _space, const Point &c, 
00028        const float _semimajor, const float _semiminor, const float _orientation) 
00029   : BaseData(_space, getStaticType()),
00030     center_pt(c), semimajor(_semimajor), semiminor(_semiminor), orientation(_orientation)
00031 { if ( semimajor < semiminor ) {
00032     swap(semimajor,semiminor);
00033     orientation = AngPi(float(orientation) + M_PI/2);
00034   }
00035   center_pt.setRefFrameType(getRefFrameType());
00036   mobile = ELLIPSE_DATA_MOBILE;
00037 }
00038   
00039 DATASTUFF_CC(EllipseData);
00040 
00041 BoundingBox2D EllipseData::getBoundingBox() const {
00042   float t_x = atan(-semiminor * tan(orientation) / semimajor);
00043   float t_y = atan( semiminor / tan(orientation) / semimajor);
00044   BoundingBox2D b;
00045   // derived from parametrization of the ellipse
00046   float o_sin = sin(orientation), t_x_sin = sin(t_x), t_y_sin = sin(t_y);
00047   float o_cos = cos(orientation), t_x_cos = cos(t_x), t_y_cos = cos(t_y);
00048   b.expand(fmat::pack(center_pt.coordX() + semimajor*t_x_cos*o_cos - semiminor*t_x_sin*o_sin,
00049                       center_pt.coordY() + semiminor*t_y_sin*o_cos + semimajor*t_y_cos*o_sin));
00050   // shift t by PI for both x and y
00051   t_x += M_PI; t_y += M_PI;
00052   t_x_sin = -t_x_sin;
00053   t_x_cos = -t_x_cos;
00054   t_y_sin = -t_y_sin;
00055   t_y_cos = -t_y_cos;
00056   b.expand(fmat::pack(center_pt.coordX() + semimajor*t_x_cos*o_cos - semiminor*t_x_sin*o_sin,
00057                       center_pt.coordY() + semiminor*t_y_sin*o_cos + semimajor*t_y_cos*o_sin));
00058   return b;
00059 }
00060 
00061 bool EllipseData::isMatchFor(const ShapeRoot& other) const {
00062   if (!(isSameTypeAs(other) && isSameColorAs(other)))
00063     return false;
00064   const Shape<EllipseData>& other_ellipse = ShapeRootTypeConst(other,EllipseData);
00065   float dist = center_pt.distanceFrom(other_ellipse->centerPt());
00066   return dist < 2*max(semimajor,other_ellipse->semimajor); // *** DST hack
00067 }
00068 
00069 bool EllipseData::isAdmissible() const {
00070   return (semimajor >= VRmixin::mapBuilder->curReq->minEllipseSemiMajor);
00071 }
00072 
00073 bool EllipseData::updateParams(const ShapeRoot& other, bool) {
00074   const Shape<EllipseData>& other_ellipse = ShapeRootTypeConst(other,EllipseData);
00075   if (other_ellipse->confidence <= 0)
00076     return false;
00077   const int other_conf = other_ellipse->confidence;
00078   center_pt = (center_pt*confidence + other_ellipse->centerPt()*other_conf) / (confidence+other_conf);
00079   semimajor = (semimajor*confidence + other_ellipse->getSemimajor()*other_conf) / (confidence+other_conf);
00080   semiminor = (semiminor*confidence + other_ellipse->getSemiminor()*other_conf) / (confidence+other_conf);
00081   orientation = orientation*((orientation_t)confidence/(confidence+other_conf))
00082     + other_ellipse->getOrientation()*((orientation_t)confidence/(confidence+other_conf));
00083   return true;
00084 }
00085 
00086 //! Print information about this shape. (Virtual in BaseData.)
00087 void EllipseData::printParams() const {
00088   cout << "Type = " << getTypeName() << "  ID=" << getId() << "  ParentID=" << getParentId() << endl;
00089   printf("  color = %d %d %d\n",getColor().red,getColor().green,getColor().blue);
00090   cout << "  center = " << centerPt() << endl;
00091   cout << "  semimajor = " << getSemimajor()
00092        << ", semiminor = " << getSemiminor()
00093        << ", orientation = " << getOrientation() << endl;
00094   cout << "  mobile = " << getMobile() << ", viewable = " << isViewable() << endl;
00095 }
00096 
00097 pair<Point,Point> EllipseData::findFeaturePoints() const {
00098   const AngPi theta1 = getOrientation();
00099   const float d1 = getSemimajor();
00100   const fmat::Column<3> from_center1 = fmat::pack(d1*cos(theta1), d1*sin(theta1), 0.f);
00101   const Point majorPt = Point(from_center1) + center_pt;
00102 
00103   const float d2 = getSemiminor();
00104   const AngPi theta2 = theta1 + AngPi((orientation_t)M_PI/2);
00105   const fmat::Column<3> from_center2 = fmat::pack(d2*sin(theta2), d2*cos(theta2), 0.f);
00106   const Point minorPt = Point(from_center2) + center_pt;
00107 
00108   return pair<Point,Point>(majorPt,minorPt);
00109 }
00110 
00111 //! Transformations. (Virtual in BaseData.)
00112 void EllipseData::applyTransform(const fmat::Transform& Tmat, const ReferenceFrameType_t newref) {
00113   pair<Point,Point> featurePts = findFeaturePoints();
00114   center_pt.applyTransform(Tmat,newref);
00115   //  orientation = orientation - (AngTwoPi)atan2(Tmat(1,2),Tmat(1,1));
00116   featurePts.first.applyTransform(Tmat,newref);
00117   featurePts.second.applyTransform(Tmat,newref);
00118   updateProperties(featurePts.first, featurePts.second);
00119 }
00120 
00121 void EllipseData::updateProperties(const Point& majorPt, const Point& minorPt) {
00122   setSemiminor(minorPt.xyDistanceFrom(center_pt));
00123   setSemimajor(majorPt.xyDistanceFrom(center_pt));
00124   setOrientation(atan2(majorPt.coordY()-center_pt.coordY(), majorPt.coordX()-center_pt.coordX()));
00125 }
00126 
00127 void EllipseData::projectToGround(const fmat::Transform& camToBase, const PlaneEquation& groundplane) {
00128   pair<Point,Point> featurePts = findFeaturePoints();
00129   center_pt.projectToGround(camToBase,groundplane);
00130   featurePts.first.projectToGround(camToBase,groundplane);  
00131   featurePts.second.projectToGround(camToBase,groundplane);
00132   updateProperties(featurePts.first, featurePts.second);
00133 }
00134 
00135 //! Functions to set properties.
00136 //{
00137 void EllipseData::setOrientation(const AngPi _orientation) {
00138   orientation = AngPi(_orientation);
00139   deleteRendering();
00140 }
00141 
00142 void EllipseData::setSemimajor(float _semimajor) {
00143   semimajor = _semimajor;
00144   deleteRendering();
00145 }
00146 
00147 void EllipseData::setSemiminor(float _semiminor) {
00148   semiminor = _semiminor;
00149   deleteRendering();
00150 }
00151 //}
00152 
00153 
00154 bool EllipseData::AreaLessThan::operator() (const Shape<EllipseData> &ellipse1, const Shape<EllipseData> &ellipse2) const {
00155       return ellipse1->getArea() < ellipse2->getArea();
00156 }
00157 
00158 // ==================================================
00159 // BEGIN SKETCH MANIPULATION AND ELLIPSE EXTRACTION CODE
00160 // ==================================================
00161 
00162 
00163 //! Ellipse extraction.
00164 
00165 std::vector<Shape<EllipseData> > EllipseData::extractEllipses(const Sketch<bool>& sketch) {
00166   const float AREA_TOLERANCE = 0.5f;
00167   const int REGION_THRESH = 25;
00168   NEW_SKETCH_N(labels,uint,visops::oldlabelcc(sketch,visops::EightWayConnect));
00169   list<Region> regionlist = Region::extractRegions(labels,REGION_THRESH);
00170   std::vector<Shape<EllipseData> > ellipses;
00171   
00172   if(regionlist.empty())
00173     return ellipses;
00174   
00175   typedef list<Region>::iterator R_IT;
00176   for (R_IT it = regionlist.begin(); it != regionlist.end(); ++it) {
00177     float ratio = it->findSemiMajorAxisLength()/(float)(it->findSemiMinorAxisLength());
00178     if((ratio < 3.0) && (ratio > 1.0f/3.0f)
00179        && (it->findArea() > M_PI*2.0*(it->findSemiMajorAxisLength())
00180      *2.0*(it->findSemiMinorAxisLength())*AREA_TOLERANCE/4.0)) {
00181       Shape<EllipseData> temp_ellipse(*it);
00182       temp_ellipse->setParentId(sketch->getViewableId());
00183       temp_ellipse->setColor(sketch->getColor());
00184       ellipses.push_back(Shape<EllipseData>(temp_ellipse));
00185     };
00186   }
00187   return ellipses;
00188 }
00189 
00190 
00191 //! Render into a sketch space and return reference. (Private.)
00192 Sketch<bool>* EllipseData::render() const {
00193   SketchSpace &SkS = space->getDualSpace();
00194   fmat::Column<3> ctr(centerPt().getCoords());
00195   SkS.applyTmat(ctr);
00196   const float &cx = ctr[0];
00197   const float &cy = ctr[1];
00198   const fmat::Transform &Tmat = SkS.getTmat();
00199   fmat::Column<2> ori;
00200   ori[0] = cos(orientation);
00201   ori[1] = sin(orientation);
00202   fmat::Matrix<2,2> rot;
00203   rot(0,0) = Tmat(0,0);
00204   rot(0,1) = Tmat(0,1);
00205   rot(1,0) = Tmat(1,0);
00206   rot(1,1) = Tmat(1,1);
00207   ori = rot * ori;
00208   const float &cosT = ori[0];
00209   const float &sinT = ori[1];
00210   const float xRange = semimajor;  // don't scale this because cosT and sinT are scaled
00211   const float majorSq = xRange*xRange;
00212   const float mnrDevMjr = semiminor/semimajor;
00213   Sketch<bool> result(SkS, "render("+getName()+")");
00214   result = 0;
00215   for (float xDist = -xRange; xDist <= xRange; xDist+=0.2f) {
00216     const float yRange = sqrt(max((float)0, majorSq - xDist*xDist)) * mnrDevMjr;
00217     for (float yDist = -yRange; yDist <= yRange; yDist+=0.2f) {
00218       int const px = round(cx+xDist*cosT-yDist*sinT);
00219       int const py = round(cy+yDist*cosT+xDist*sinT);
00220       if ( px >= 0 && px < result.width &&
00221            py >= 0 && py < result.height )
00222         result(px,py) = true;
00223     }
00224   }
00225   return new Sketch<bool>(result);
00226 }
00227 
00228 } // namespace

DualCoding 5.1CVS
Generated Mon May 9 04:56:25 2016 by Doxygen 1.6.3