Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

Point.cc

Go to the documentation of this file.
00001 //-*-c++-*-
00002 
00003 #include <math.h>
00004 
00005 #include "Shared/Config.h"
00006 #include "Motion/Kinematics.h"
00007 
00008 #include "Shared/Measures.h"
00009 #include "Point.h"
00010 #include "LineData.h"
00011 #include "ShapeTypes.h"  // for ReferenceFrameType_t
00012 #include "VRmixin.h"
00013 #include "SketchSpace.h"
00014 
00015 #ifdef PLATFORM_APERIOS
00016 //! this is normally defined in <math.h>, but the OPEN-R cross-compiler isn't configured right
00017 template<typename T> static inline int signbit(T x) { return x<0; }
00018 #endif
00019 
00020 using namespace std;
00021 
00022 namespace DualCoding {
00023 
00024 float Point::distanceFrom(const Point& otherPt) const {
00025   return (coords - otherPt.coords).norm();
00026 }
00027 
00028 float Point::xyDistanceFrom(const Point& other) const {
00029   float dx = coordX() - other.coordX();
00030   float dy = coordY() - other.coordY();
00031   return sqrt(dx*dx + dy*dy);
00032 }
00033 
00034 AngSignPi Point::atanYX() const {
00035   return atan2(coordY(), coordX());
00036 }
00037 
00038 float Point::xyNorm() const { return sqrt(coordX()*coordX() + coordY()*coordY()); }
00039 
00040 float Point::xyzNorm() const { return sqrt(coordX()*coordX() + coordY()*coordY() + coordZ()*coordZ()); }
00041 
00042 Point Point::unitVector() const {
00043   return (*this) / xyzNorm();
00044 }
00045 
00046 
00047 bool Point::isLeftOf(const Point& other, float distance) const {
00048   switch ( refFrameType ) {
00049   case camcentric:
00050     return coordX()+distance < other.coordX();
00051   case egocentric:  
00052     return coordY()-distance > other.coordY();
00053   case allocentric: {
00054     // Calculate bearings to both points from current
00055     // agent location and check sign of the difference
00056     AngSignPi thisBearing = ((*this)-VRmixin::theAgent->getCentroid()).atanYX();
00057     AngSignPi otherBearing = (other-VRmixin::theAgent->getCentroid()).atanYX();
00058     AngSignPi diff = thisBearing - otherBearing;
00059     return diff > 0;
00060     //cout << "Allocentric Point::isLeftOf fudged for now" << endl;
00061     //return coordY()-distance > other.coordY();
00062   }
00063   default:
00064     cout<<"Unspecified reference frame for Point::isLeftOf"<<endl;
00065     return false;
00066   }
00067 }
00068 
00069 bool Point::isRightOf(const Point& other, float distance) const {
00070   return other.isLeftOf(*this,distance); }
00071 
00072 bool Point::isAbove(const Point& other,float distance) const {
00073   switch ( refFrameType ) {
00074   case camcentric:
00075     return coordY()+distance < other.coordY();
00076   case egocentric:  
00077     return coordX()-distance > other.coordX();
00078   case allocentric:
00079     // cout << "Allocentric Point::isAbove fudged for now" << endl;
00080     return coordX()-distance > other.coordX();
00081     // Should really calculate bearings to both points from current
00082     // agent location and check sign of the difference
00083   default:
00084     cout<<"Unspecified reference frame for Point::isAbove"<<endl;
00085     return false;
00086   }
00087 }
00088 
00089 bool Point::isBelow(const Point& other, float distance) const {
00090   return other.isAbove(*this,distance); }
00091 
00092 
00093 //! Apply a transformation matrix to translate and/or rotate  the point.
00094 void Point::applyTransform(const fmat::Transform& Tmat, const ReferenceFrameType_t newref) {
00095   fmat::Column<3> tmp = Tmat*fmat::SubVector<3>(&coords[0]);
00096   coords[0] = tmp[0];
00097   coords[1] = tmp[1];
00098   coords[2] = tmp[2];
00099   if ( newref != unspecified )
00100     refFrameType = newref;
00101 }
00102 
00103 bool Point::projectToGround(const fmat::Transform& camToBase, const PlaneEquation& groundplane) {
00104   const float xres = VRmixin::camSkS.getWidth();
00105   const float yres = VRmixin::camSkS.getHeight();
00106   const float maxres = max(xres,yres);
00107   const float normX = float(2*coordX() - xres)/maxres;
00108   const float normY = float(2*coordY() - yres)/maxres;
00109   fmat::Column<3> camera_vector;
00110   config->vision.computeRay(normX, normY, camera_vector[0], camera_vector[1], camera_vector[2]);
00111   
00112   /*! Mathematical implementation:
00113    *  
00114    *  We'll convert the ray to the plane's reference frame, solve there.
00115    *  We find a point on the ray (ro_b) and the direction of the ray (rv_b).
00116    */
00117   fmat::Column<3> ro_b = camToBase.translation();
00118   fmat::Column<3> rv_b = camToBase.rotation() * camera_vector;
00119   
00120   /*! Find distance from the ray offset (ro_b) and the closest point on the plane. */
00121   float dist = groundplane.getDisplacement() - fmat::dotProduct(ro_b, groundplane.getDirection());
00122   /*! Find scaling factor by projecting ray vector (rv_b) onto plane normal. */
00123   float align = fmat::dotProduct(rv_b, groundplane.getDirection());
00124   
00125   /*! Intersection point will be rv_b*dist/align + ro_b, but need to watch out
00126    *  for case where align==0 (rv_b and plane are parallel, no intersection) */
00127   refFrameType = egocentric;
00128   if ( std::abs(align) > numeric_limits<float>::epsilon() ) {
00129     coords = rv_b * (dist/align) + ro_b;
00130     /*
00131     std::cout << "Point.cc:  gdisp=" << groundplane.getDisplacement() << "  gdir=" << groundplane.getDirection() << endl;
00132     std::cout << "  dprod = " << fmat::dotProduct(ro_b, groundplane.getDirection()) << "    dist=" << dist << endl;
00133     std::cout << "  align=" << align << "   scale=" << dist/align << endl;
00134     std::cout << "  coord=" << coords << "  rv_b=" << rv_b << "  ro_b=" << ro_b << endl;
00135     */
00136     return true;
00137   } else if ( align!=0 && dist!=0 && signbit(align)!=signbit(dist) ) {
00138     coords = -rv_b * 1.0e6f;
00139     return false;
00140   } else {
00141     coords = rv_b * 1.0e6f;
00142     return false;
00143   }
00144 }
00145 
00146 bool Point::projectToGround(int xres, int yres, const PlaneEquation& groundplane) {
00147 #ifdef TGT_HAS_CAMERA
00148   // Normalize coordinate system to [-1,+1]
00149     const float normX = float(2*coordX() - xres)/xres;
00150     const float normY = float(2*coordY() - yres)/xres;
00151   fmat::Column<3> camera_vector;
00152   config->vision.computeRay(normX, normY, camera_vector[0],camera_vector[1],camera_vector[2]);
00153   fmat::Column<4> ground_point = kine->projectToPlane(CameraFrameOffset, camera_vector, BaseFrameOffset, groundplane, BaseFrameOffset);
00154   coords = fmat::SubVector<3>(ground_point);
00155   if(ground_point[3]!=1) {
00156     // only happens if parallel to ground (or almost so), just scale by a big value (instead of divide-by-zero)
00157     // this retains the direction for looking at an object
00158     coords*=1.0e6f;
00159     return false;
00160   }
00161   return true;
00162   //  std::cout << "Ground plane: " << NEWMAT::printmat(ground_plane) << 
00163   //    "  camera_point: " << NEWMAT::printmat(camera_point) << 
00164   //    "  ground_point: " << NEWMAT::printmat(ground_point) << std::endl;
00165 #else
00166   return false;
00167 #endif
00168 }
00169   
00170 
00171 // Calling point and groundPoint must both have been projectToGround'ed already
00172 float Point::getHeightAbovePoint(const Point& groundPoint, const PlaneEquation& groundplane) {
00173 #ifndef TGT_HAS_CAMERA
00174   return groundPoint.coordZ();
00175 #else
00176   fmat::Transform baseToCam = kine->linkToBase(CameraFrameOffset);
00177   fmat::Column<3> camOffset = baseToCam.translation();
00178   //std::cout<<std::endl;
00179   //std::cout<<"cam offset = "<<NEWMAT::printmat(camOffset)<<std::endl;
00180   //std::cout<<"groundPlane = "<<NEWMAT::printmat(groundplane)<<std::endl;
00181   camOffset -= groundplane.getDirection()*groundplane.getDisplacement();
00182   
00183   //std::cout<<"top pt coords = "<<NEWMAT::printmat(coords)<<std::endl;
00184   float dx = camOffset[0] - coords[0];
00185   float dy = camOffset[1] - coords[1];
00186   float dz = camOffset[2] - coords[2];
00187   //std::cout<<"Cam to point = "<<dx<<" "<<dy<<" "<<dz<<std::endl;
00188   float dHorizCam = sqrt(dx*dx + dy*dy);
00189   
00190   Point dP = groundPoint - *this;
00191   float dHorizPoint = sqrt(dP.coordX()*dP.coordX() + dP.coordY()*dP.coordY());
00192   
00193   return dz*dHorizPoint/dHorizCam;
00194 #endif
00195 }
00196 
00197 
00198 Point Point::operator+ (const Point& b) const { return Point(*this) += b; }
00199 
00200 Point& Point::operator+= (const Point& b) {
00201   coords += b.coords;
00202   makeRefFrameCompatible(b);
00203   return *this;
00204 }
00205 
00206 Point Point::operator- (const Point& b) const { return Point(*this) -= b; }
00207 
00208 Point& Point::operator-= (const Point& b) {
00209   coords -= b.coords;
00210   makeRefFrameCompatible(b);
00211   return *this;
00212 }
00213 
00214 void Point::makeRefFrameCompatible(const Point &other) {
00215   refFrameType = ( refFrameType == unspecified || refFrameType == other.refFrameType ) ?
00216     other.refFrameType : unspecified;
00217 }
00218 
00219 Point Point::operator* (float const b) const { return Point(coords*b,refFrameType); }
00220 
00221 Point& Point::operator *= (float const b) {
00222   coords *= b;
00223   return *this;
00224 }
00225 
00226 
00227 Point Point::operator/ (float const b) const { return Point(coords/b,refFrameType); }
00228 
00229 Point& Point::operator /= (float const b) {
00230   coords /= b;
00231   return *this;
00232 }
00233 
00234 bool Point::operator== (const Point& b) const {
00235   return (coordX() == b.coordX() 
00236           && coordY() == b.coordY() 
00237           && coordZ() == b.coordZ());
00238 }
00239 
00240 void Point::printData() const {
00241   cout<<"{"<<coordX()<<","<<coordY()<<","<<coordZ()<<"}";
00242 }
00243 
00244 } // namespace

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