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