00001
00002 #include <iostream>
00003 #include <vector>
00004 #include <list>
00005 #include <math.h>
00006
00007 #include "BaseData.h"
00008 #include "Point.h"
00009 #include "Measures.h"
00010 #include "ShapeTypes.h"
00011
00012 #include "SketchSpace.h"
00013 #include "Sketch.h"
00014 #include "Region.h"
00015 #include "visops.h"
00016
00017 #include "ShapeSpace.h"
00018 #include "ShapeRoot.h"
00019
00020 #include "EllipseData.h"
00021 #include "ShapeEllipse.h"
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 : BaseData(_space, getStaticType()),
00029 center_pt(c), semimajor(0), semiminor(0), orientation(0)
00030 { center_pt.setRefFrameType(getRefFrameType());
00031 mobile = ELLIPSE_DATA_MOBILE; }
00032
00033 DATASTUFF_CC(EllipseData);
00034
00035 BoundingBox EllipseData::getBoundingBox() const {
00036 float o_sin = sin(orientation);
00037 float o_cos = cos(orientation);
00038 Point major_tip(semimajor*o_cos, semimajor*o_sin);
00039 Point minor_tip(-semiminor*o_sin, semiminor*o_cos);
00040 return BoundingBox(BoundingBox(BoundingBox(center_pt+major_tip),
00041 BoundingBox(center_pt-major_tip)),
00042 BoundingBox(BoundingBox(center_pt+minor_tip),
00043 BoundingBox(center_pt-minor_tip)));
00044 }
00045
00046 bool EllipseData::isMatchFor(const ShapeRoot& other) const {
00047 if (!(isSameTypeAs(other) && isSameColorAs(other)))
00048 return false;
00049 const Shape<EllipseData>& other_ellipse = ShapeRootTypeConst(other,EllipseData);
00050 float dist = center_pt.distanceFrom(other_ellipse->centerPt());
00051 return dist < 2*max(semimajor,other_ellipse->semimajor);
00052 }
00053
00054 bool EllipseData::updateParams(const ShapeRoot& other, bool) {
00055 const Shape<EllipseData>& other_ellipse = ShapeRootTypeConst(other,EllipseData);
00056 if (other_ellipse->confidence <= 0)
00057 return false;
00058 const int other_conf = other_ellipse->confidence;
00059 center_pt = (center_pt*confidence + other_ellipse->centerPt()*other_conf) / (confidence+other_conf);
00060 semimajor = (semimajor*confidence + other_ellipse->getSemimajor()*other_conf) / (confidence+other_conf);
00061 semiminor = (semiminor*confidence + other_ellipse->getSemiminor()*other_conf) / (confidence+other_conf);
00062 orientation = orientation*((orientation_t)confidence/(confidence+other_conf))
00063 + other_ellipse->getOrientation()*((orientation_t)confidence/(confidence+other_conf));
00064 return true;
00065 }
00066
00067
00068 void
00069 EllipseData::printParams() const {
00070 cout << "Type = " << getTypeName();
00071 cout << "Shape ID = " << getId() << endl;
00072 cout << "Parent ID = " << getParentId() << endl;
00073
00074
00075 cout << endl;
00076 cout << "center{" << centerPt().coordX() << ", " << centerPt().coordY() << "}" << endl;
00077
00078 cout << "semimajor = " << getSemimajor() << endl;
00079 cout << "semiminor = " << getSemiminor() << endl;
00080 cout << "orientation = " << getOrientation() << endl;
00081 printf("color = %d %d %d\n",getColor().red,getColor().green,getColor().blue);
00082 cout << "mobile = " << isMobile() << endl;
00083 cout << "viewable = " << isViewable() << endl;
00084 }
00085
00086 pair<Point,Point> EllipseData::findFeaturePoints() const {
00087 AngPi theta = getOrientation();
00088 NEWMAT::ColumnVector from_center(4);
00089
00090 float dl = getSemimajor();
00091 from_center << dl*cos(theta) << dl*sin(theta) << 0 << 0;
00092 Point majorPt(from_center);
00093 majorPt += center_pt;
00094
00095 dl = getSemiminor();
00096 theta = theta + (AngPi) (M_PI/2);
00097 from_center << dl*sin(theta) << dl*cos(theta) << 0 << 0;
00098 Point minorPt(from_center);
00099 minorPt += center_pt;
00100 return pair<Point,Point>(majorPt,minorPt);
00101 }
00102
00103
00104 void EllipseData::applyTransform(const NEWMAT::Matrix& Tmat) {
00105 pair<Point,Point> featurePts = findFeaturePoints();
00106 center_pt.applyTransform(Tmat);
00107
00108 featurePts.first.applyTransform(Tmat);
00109 featurePts.second.applyTransform(Tmat);
00110 updateProperties(featurePts.first, featurePts.second);
00111 }
00112
00113 void EllipseData::updateProperties(const Point& majorPt, const Point& minorPt) {
00114 setSemiminor(minorPt.xyDistanceFrom(center_pt));
00115 setSemimajor(majorPt.xyDistanceFrom(center_pt));
00116 setOrientation(atan2(majorPt.coords(2)-center_pt.coords(2),majorPt.coords(1)-center_pt.coords(1)));
00117 }
00118
00119 void EllipseData::projectToGround(const NEWMAT::Matrix& camToBase,
00120 const NEWMAT::ColumnVector& 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
00148
00149
00150
00151
00152
00153
00154 std::vector<Shape<EllipseData> > EllipseData::extractEllipses(const Sketch<bool>& sketch)
00155 {
00156 const float AREA_TOLERANCE = 0.5;
00157 const int REGION_THRESH = 25;
00158 NEW_SKETCH_N(labels,usint,visops::oldlabelcc(sketch,visops::EightWayConnect));
00159 list<Region> regionlist = Region::extractRegions(labels,REGION_THRESH);
00160 std::vector<Shape<EllipseData> > ellipses;
00161
00162 if(regionlist.empty())
00163 return ellipses;
00164
00165 typedef list<Region>::iterator R_IT;
00166 for (R_IT it = regionlist.begin(); it != regionlist.end(); ++it) {
00167 float ratio = it->findSemiMajorAxisLength()/(float)(it->findSemiMinorAxisLength());
00168 if((ratio < 2.0) && (ratio > 1.0/(float)2.0)
00169 && (it->findArea() > M_PI*2.0*(it->findSemiMajorAxisLength())
00170 *2.0*(it->findSemiMinorAxisLength())*AREA_TOLERANCE/4.0)) {
00171 Shape<EllipseData> temp_ellipse(*it);
00172 temp_ellipse->setParentId(sketch->getViewableId());
00173 temp_ellipse->setColor(sketch->getColor());
00174 ellipses.push_back(Shape<EllipseData>(temp_ellipse));
00175 };
00176 }
00177 return ellipses;
00178 }
00179
00180
00181
00182 Sketch<bool>* EllipseData::render() const {
00183 SketchSpace &SkS = space->getDualSpace();
00184 NEWMAT::ColumnVector ctr(centerPt().getCoords());
00185 SkS.applyTmat(ctr);
00186 const float &cx = ctr(1);
00187 const float &cy = ctr(2);
00188 const NEWMAT::Matrix &Tmat = SkS.getTmat();
00189 NEWMAT::ColumnVector ori(2);
00190 ori << cos(orientation) << sin(orientation);
00191 NEWMAT::Matrix rot(2,2);
00192 rot(1,1) = Tmat(1,1);
00193 rot(1,2) = Tmat(1,2);
00194 rot(2,1) = Tmat(2,1);
00195 rot(2,2) = Tmat(2,2);
00196 ori = rot * ori;
00197 const float &cosT = ori(1);
00198 const float &sinT = ori(2);
00199 const float xRange = semimajor / Tmat(4,4);
00200 const float majorSq = xRange*xRange;
00201 const float mnrDevMjr = semiminor/semimajor;
00202 Sketch<bool> result(SkS, "render("+getName()+")");
00203 result = 0;
00204 for (float xDist = -xRange; xDist <= xRange; xDist+=0.2) {
00205 const float yRange = sqrt(max((float)0, majorSq - xDist*xDist)) * mnrDevMjr;
00206 for (float yDist = -yRange; yDist <= yRange; yDist+=0.2) {
00207 int const px = round(cx+xDist*cosT-yDist*sinT);
00208 int const py = round(cy+yDist*cosT+xDist*sinT);
00209 if ( px >= 0 && px < result.width &&
00210 py >= 0 && py < result.height )
00211 result(px,py) = true;
00212 }
00213 }
00214 return new Sketch<bool>(result);
00215 }
00216
00217 }