00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 #include "Geometry.h"
00010 #include "Tools/FieldDimensions.h"
00011 #include "Tools/Debugging/Debugging.h"
00012 #include "Tools/RobotConfiguration.h"
00013 
00014 Geometry::Circle::Circle() : radius(0) 
00015 {
00016 }
00017 
00018 double Geometry::angleTo(const Pose2D& from, 
00019                                 const Vector2<double>& to)
00020 {
00021   Pose2D relPos = Pose2D(to) - from;
00022   return atan2(relPos.translation.y,relPos.translation.x);
00023 }
00024 
00025 double Geometry::distanceTo(const Pose2D& from, 
00026                                    const Vector2<double>& to)
00027 {
00028   return (Pose2D(to) - from).translation.abs();
00029 }
00030 
00031 Vector2<double> Geometry::vectorTo(const Pose2D& from, const Vector2<double>& to)
00032 {
00033   return (Pose2D(to) - from).translation;
00034 }
00035 
00036 void Geometry::Line::normalizeDirection()
00037 {
00038   double distance = 
00039     sqrt(sqr(direction.x) + sqr(direction.y));
00040   direction.x = direction.x / distance;
00041   direction.y = direction.y / distance;
00042 }
00043 
00044 Geometry::Circle Geometry::getCircle
00045 (
00046  const Vector2<int> point1,
00047  const Vector2<int> point2,
00048  const Vector2<int> point3
00049  )
00050 {
00051   double x1 = point1.x;
00052   double y1 = point1.y;
00053   double x2 = point2.x;
00054   double y2 = point2.y;
00055   double x3 = point3.x;
00056   double y3 = point3.y;
00057   
00058   Circle circle;
00059   
00060   if((x2*y1 - x3*y1 - x1*y2 + x3*y2 + x1*y3 - x2*y3 == 0) )
00061   {
00062     circle.radius = 0;
00063   }
00064   else
00065   {
00066     circle.radius =
00067       0.5 * 
00068       sqrt(
00069       ( (sqr(x1 - x2) + sqr(y1 - y2) ) *
00070       (sqr(x1 - x3) + sqr(y1 - y3) ) *
00071       (sqr(x2 - x3) + sqr(y2 - y3) )
00072       )
00073       /
00074       sqr(x2*y1 - x3*y1 - x1*y2 + x3*y2 + x1*y3 - x2*y3)
00075       );
00076   }
00077   
00078   if( (2 * (-x2*y1 + x3*y1 + x1*y2 - x3*y2 - x1*y3 + x2*y3) == 0) )
00079   {
00080     circle.center.x = 0;
00081   }
00082   else
00083   {
00084     circle.center.x =
00085       (
00086       sqr(x3) * (y1 - y2) + 
00087       (sqr(x1) + (y1 - y2) * (y1 - y3)) * (y2 - y3) +
00088       sqr(x2) * (-y1 + y3)
00089       )
00090       /
00091       (2 * (-x2*y1 + x3*y1 + x1*y2 - x3*y2 - x1*y3 + x2*y3) );
00092   }   
00093   
00094   if((2 * (x2*y1 - x3*y1 - x1*y2 + x3*y2 + x1*y3 - x2*y3) == 0) )
00095   {
00096     circle.center.y = 0;
00097   }
00098   else
00099   {
00100     circle.center.y =
00101       (
00102       sqr(x1) * (x2 - x3) + 
00103       sqr(x2) * x3 + 
00104       x3*(-sqr(y1) + sqr(y2) ) - 
00105       x2*(+sqr(x3) - sqr(y1) + sqr(y3) ) + 
00106       x1*(-sqr(x2) + sqr(x3) - sqr(y2) + sqr(y3) )
00107       )
00108       /
00109       (2 * (x2*y1 - x3*y1 - x1*y2 + x3*y2 + x1*y3 - x2*y3) );
00110   } 
00111   return circle;
00112 }
00113 
00114 bool Geometry::getIntersectionOfLines
00115 (
00116  const Line line1,
00117  const Line line2,
00118  Vector2<int>& intersection
00119  )
00120 {
00121  Vector2<double> intersectionDouble;
00122  bool toReturn = getIntersectionOfLines(line1,line2,intersectionDouble);
00123  intersection.x = (int)intersectionDouble.x;
00124  intersection.y = (int)intersectionDouble.y;
00125  return toReturn;
00126 }
00127 
00128 bool Geometry::getIntersectionOfLines
00129 (
00130  const Line line1,
00131  const Line line2,
00132  Vector2<double>& intersection
00133  )
00134 {
00135   if(line1.direction.y * line2.direction.x == line1.direction.x * line2.direction.y)
00136   {
00137     return false;
00138   }
00139   
00140   intersection.x = 
00141     line1.base.x +
00142     line1.direction.x * 
00143     (
00144     line1.base.y * line2.direction.x - 
00145     line2.base.y * line2.direction.x + 
00146     (-line1.base.x + line2.base.x) * line2.direction.y
00147     )
00148     /
00149     ( (-line1.direction.y) * line2.direction.x + line1.direction.x * line2.direction.y );
00150   
00151   intersection.y = 
00152     line1.base.y + 
00153     line1.direction.y *
00154     (
00155     -line1.base.y * line2.direction.x + 
00156     line2.base.y * line2.direction.x + 
00157     (line1.base.x - line2.base.x) * line2.direction.y
00158     )
00159     /
00160     (line1.direction.y * line2.direction.x - line1.direction.x * line2.direction.y);
00161   
00162   return true;
00163 }
00164 
00165 bool Geometry::getIntersectionOfRaysFactor
00166 (
00167  const Line ray1,
00168  const Line ray2,
00169  double& factor
00170  )
00171 {
00172   double divisor = ray2.direction.x * ray1.direction.y - ray1.direction.x * ray2.direction.y;
00173   if(divisor==0)
00174   {
00175     return false;
00176   }
00177   double k=(ray2.direction.y*ray1.base.x - ray2.direction.y*ray2.base.x - ray2.direction.x*ray1.base.y + ray2.direction.x*ray2.base.y)/divisor;
00178   double l=(ray1.direction.y*ray1.base.x - ray1.direction.y*ray2.base.x - ray1.direction.x*ray1.base.y + ray1.direction.x*ray2.base.y)/divisor;
00179   if ((k>=0)&&(l>=0)&&(k<=1)&&(l<=1))
00180   {
00181     
00182     factor=k;
00183     return true;
00184   }
00185   return false;
00186 }
00187 
00188 double Geometry::getDistanceToLine
00189 (
00190  const Line line,
00191  const Vector2<double>& point
00192  )
00193 {
00194   if (line.direction.x == 0 && line.direction.y == 0) 
00195     return distance(point, line.base);
00196 
00197   Vector2<double> normal;
00198   normal.x = line.direction.y;
00199   normal.y = -line.direction.x;
00200   normal.normalize();
00201 
00202   double c = normal * line.base;
00203 
00204   return normal * point - c;
00205 }
00206 
00207 double Geometry::getDistanceToEdge
00208 (
00209  const Line line,
00210  const Vector2<double>& point
00211  )
00212 {
00213   if (line.direction.x == 0 && line.direction.y == 0) 
00214     return distance(point, line.base);
00215 
00216   double c = line.direction * line.base;
00217 
00218   double d = (line.direction * point - c) / (line.direction * line.direction);
00219 
00220   if (d < 0) 
00221     return distance(point, line.base);
00222   else if (d > 1.0)
00223     return distance(point, line.base + line.direction);
00224   else
00225     return fabs(getDistanceToLine(line, point));
00226 }
00227 
00228 
00229 double Geometry::distance
00230 (
00231  const Vector2<double>& point1,
00232  const Vector2<double>& point2
00233  )
00234 {
00235   return (point2 - point1).abs();
00236 }
00237 
00238 double Geometry::distance
00239 (
00240  const Vector2<int>& point1,
00241  const Vector2<int>& point2
00242  )
00243 {
00244   return (point2 - point1).abs();
00245 }
00246 
00247 double Geometry::calculateScaleFactor(
00248   int y,
00249   unsigned long frameNumber,
00250   unsigned long prevFrameNumber,
00251   const CameraInfo& cameraInfo
00252   )
00253 {
00254   if(frameNumber != prevFrameNumber)
00255   {
00256     const RobotDimensions& r = getRobotConfiguration().getRobotDimensions();
00257     double timeDiff = (frameNumber - prevFrameNumber) * r.motionCycleTime; 
00258     double imageDiff = timeDiff * r.imagesPerSecond; 
00259     return (1 - double(1 + y) / cameraInfo.resolutionHeight) / imageDiff * 0.9; 
00260   }
00261   else
00262     return 0;
00263 }
00264 
00265 Vector3<double> Geometry::rayFromCamera(
00266   int y,
00267   const CameraMatrix& cameraMatrix, 
00268   const CameraMatrix& prevCameraMatrix,
00269   const Vector3<double> vector,
00270   const CameraInfo& cameraInfo
00271   )
00272 {
00273   Vector3<double> v1 = cameraMatrix.rotation * vector;
00274   if(!cameraInfo.simulated)
00275   {
00276     Vector3<double> v2 = prevCameraMatrix.rotation * vector;
00277     
00278     v1 += (v2 - v1) * calculateScaleFactor(y, cameraMatrix.frameNumber, prevCameraMatrix.frameNumber, cameraInfo);
00279   }
00280   return v1;
00281 }
00282 
00283 void Geometry::calculateAnglesForPoint
00284 (
00285  const Vector2<int>& point, 
00286  const CameraMatrix& cameraMatrix, 
00287  const CameraInfo& cameraInfo, 
00288  Vector2<double>& angles
00289  )
00290 {
00291   double factor = cameraInfo.focalLength;
00292   
00293   Vector3<double> vectorToPoint(
00294     factor,
00295     cameraInfo.opticalCenter.x - point.x,
00296     cameraInfo.opticalCenter.y - point.y);
00297   
00298   Vector3<double> vectorToPointWorld = 
00299     cameraMatrix.rotation * vectorToPoint;
00300   
00301   angles.x =
00302     atan2(vectorToPointWorld.y,vectorToPointWorld.x);
00303   
00304   angles.y =
00305     atan2(
00306     vectorToPointWorld.z,
00307     sqrt(sqr(vectorToPointWorld.x) + sqr(vectorToPointWorld.y)) 
00308     );
00309 }
00310 
00311 void Geometry::calculateAnglesForPoint
00312 (
00313  const Vector2<int>& point, 
00314  const CameraMatrix& cameraMatrix, 
00315  const CameraMatrix& prevCameraMatrix, 
00316  const CameraInfo& cameraInfo, 
00317  Vector2<double>& angles
00318  )
00319 {
00320   calculateAnglesForPoint(point, cameraMatrix, cameraInfo, angles);
00321   if(!cameraInfo.simulated)
00322   {
00323     Vector2<double> angles2;
00324     calculateAnglesForPoint(point, prevCameraMatrix, cameraInfo, angles2);
00325     
00326     angles += (angles2 - angles) * calculateScaleFactor(point.y, cameraMatrix.frameNumber, prevCameraMatrix.frameNumber, cameraInfo);
00327   }
00328 }
00329   
00330 void Geometry::calculatePointByAngles
00331 (
00332  const Vector2<double>& angles,
00333  const CameraMatrix& cameraMatrix, 
00334  const CameraInfo& cameraInfo, 
00335  Vector2<int>& point
00336  )
00337 {
00338   Vector3<double> vectorToPointWorld, vectorToPoint;
00339   vectorToPointWorld.x = cos(angles.x);
00340   vectorToPointWorld.y = sin(angles.x);
00341   vectorToPointWorld.z = tan(angles.y);
00342   
00343   RotationMatrix rotationMatrix = cameraMatrix.rotation;
00344   vectorToPoint = rotationMatrix.invert() * vectorToPointWorld;
00345   
00346   double factor = cameraInfo.focalLength;
00347   
00348   double scale = factor / vectorToPoint.x;
00349   
00350   point.x = (int)(0.5 + cameraInfo.opticalCenter.x - vectorToPoint.y * scale);
00351   point.y = (int)(0.5 + cameraInfo.opticalCenter.y  - vectorToPoint.z * scale);
00352 }
00353 
00354 
00355 bool Geometry::clipLineWithQuadrangle
00356 (
00357  const Line lineToClip,
00358  const Vector2<double>& corner0, 
00359  const Vector2<double>& corner1,
00360  const Vector2<double>& corner2, 
00361  const Vector2<double>& corner3,
00362  Vector2<int>& clipPoint1, 
00363  Vector2<int>& clipPoint2
00364  )
00365 {
00366   Vector2<double> point1, point2;
00367   bool toReturn = clipLineWithQuadrangle(
00368    lineToClip,
00369    corner0, corner1, corner2, corner3,
00370    point1, point2);
00371    clipPoint1.x = (int)point1.x;
00372    clipPoint1.y = (int)point1.y;
00373    clipPoint2.x = (int)point2.x;
00374    clipPoint2.y = (int)point2.y;
00375    return toReturn;
00376 }
00377 
00378 bool Geometry::clipLineWithQuadrangle
00379 (
00380  const Line lineToClip,
00381  const Vector2<double>& corner0, 
00382  const Vector2<double>& corner1,
00383  const Vector2<double>& corner2, 
00384  const Vector2<double>& corner3,
00385  Vector2<double>& clipPoint1, 
00386  Vector2<double>& clipPoint2
00387  )
00388 {
00389   Geometry::Line side[4] , verticalLine;
00390 
00391   verticalLine.base = lineToClip.base;
00392 
00393   verticalLine.direction.x = -lineToClip.direction.y;
00394   verticalLine.direction.y = lineToClip.direction.x;
00395   
00396   Vector2<double> corner[4];
00397   corner[0] = corner0;
00398   corner[1] = corner1;
00399   corner[2] = corner2;
00400   corner[3] = corner3;
00401 
00402   side[0].base = corner0;
00403   side[0].direction = corner1;
00404   
00405   side[1].base = corner1;
00406   side[1].direction = corner3;
00407   
00408   side[2].base = corner2;
00409   side[2].direction = corner1;
00410   
00411   side[3].base = corner3;
00412   side[3].direction = corner3;
00413   
00414   Vector2<double> point1, point2, point;
00415   bool nextIsPoint1 = true;
00416   
00417 
00418 
00419 
00420 
00421 
00422 
00423 
00424 
00425 
00426 
00427 
00428 
00429 
00430 
00431 
00432   if(Geometry::getIntersectionOfLines(side[0], lineToClip, point))
00433   {
00434     if(corner[0].x < point.x && point.x < corner[1].x)
00435     {
00436       if(nextIsPoint1)
00437       {
00438         point1 = point;
00439         nextIsPoint1 = false;
00440       }
00441     }
00442   }
00443 
00444   if(Geometry::getIntersectionOfLines(side[1], lineToClip, point))
00445   {
00446     if(corner[1].y < point.y && point.y < corner[2].y)
00447     {
00448       if(nextIsPoint1)
00449       {
00450         point1 = point;
00451         nextIsPoint1 = false;
00452       }
00453       else
00454       point2 = point;
00455     }
00456   }
00457 
00458   if(Geometry::getIntersectionOfLines(side[2], lineToClip, point))
00459   {
00460     if(corner[2].x > point.x && point.x > corner[3].x)
00461     {
00462       if(nextIsPoint1)
00463       {
00464         point1 = point;
00465         nextIsPoint1 = false;
00466       }
00467       else
00468       point2 = point;
00469     }
00470   }
00471 
00472   if(Geometry::getIntersectionOfLines(side[3], lineToClip, point))
00473   {
00474     if(corner[3].y > point.y && point.y > corner[0].y)
00475     {
00476       if(nextIsPoint1)
00477       {
00478         point1 = point;
00479         nextIsPoint1 = false;
00480       }
00481       else
00482       point2 = point;
00483     }
00484   }
00485 
00486   if(nextIsPoint1)
00487     return false;
00488 
00489   if(getDistanceToLine(verticalLine, point1) < getDistanceToLine(verticalLine, point2) )
00490   {
00491     clipPoint1 = point1;
00492     clipPoint2 = point2;
00493   }
00494   else
00495   {
00496     clipPoint1 = point2;
00497     clipPoint2 = point1;
00498   }
00499   return true;
00500 }
00501 
00502 bool Geometry::isPointInsideRectangle
00503 (
00504  const Vector2<double>& bottomLeftCorner, 
00505  const Vector2<double>& topRightCorner,
00506  const Vector2<double>& point
00507 )
00508 {
00509   return(
00510     bottomLeftCorner.x <= point.x && point.x <= topRightCorner.x &&
00511     bottomLeftCorner.y <= point.y && point.y <= topRightCorner.y
00512     );
00513 }
00514 
00515 bool Geometry::isPointInsideRectangle
00516 (
00517  const Vector2<int>& bottomLeftCorner, 
00518  const Vector2<int>& topRightCorner,
00519  const Vector2<int>& point
00520 )
00521 {
00522   return(
00523     bottomLeftCorner.x <= point.x && point.x <= topRightCorner.x &&
00524     bottomLeftCorner.y <= point.y && point.y <= topRightCorner.y
00525     );
00526 }
00527 
00528 bool Geometry::clipPointInsideRectange(
00529   const Vector2<int>& bottomLeftCorner, 
00530   const Vector2<int>& topRightCorner,
00531   Vector2<int>& point
00532 )
00533 {
00534   bool clipped = false;
00535   if (point.x < bottomLeftCorner.x)
00536   {
00537     point.x = bottomLeftCorner.x;
00538     clipped = true;
00539   }
00540   if (point.x > topRightCorner.x)
00541   {
00542     point.x = topRightCorner.x;
00543     clipped = true;
00544   }
00545   if (point.y < bottomLeftCorner.y)
00546   {
00547     point.y = bottomLeftCorner.y;
00548     clipped = true;
00549   }
00550   if (point.y > topRightCorner.y)
00551   {
00552     point.y = topRightCorner.y;
00553     clipped = true;
00554   }
00555   return clipped;
00556 }
00557 
00558 bool Geometry::calculatePointOnField
00559 (
00560  const int x,
00561  const int y,
00562  const CameraMatrix& cameraMatrix,
00563  const CameraInfo& cameraInfo,
00564  Vector2<int>& pointOnField
00565  )
00566 {
00567 #ifndef _WIN32 // don't recalculate on real robot
00568   static 
00569 #endif
00570   double xFactor = cameraInfo.focalLengthInv,
00571          yFactor = cameraInfo.focalLengthInv;
00572 
00573   Vector3<double> 
00574     vectorToCenter(1, (cameraInfo.opticalCenter.x - x) * xFactor, (cameraInfo.opticalCenter.y - y) * yFactor);
00575   
00576   Vector3<double> 
00577     vectorToCenterWorld = cameraMatrix.rotation * vectorToCenter;
00578 
00579   
00580   if(vectorToCenterWorld.z > -5 * yFactor) return false;
00581   
00582   double a1 = cameraMatrix.translation.x,
00583          a2 = cameraMatrix.translation.y,
00584          a3 = cameraMatrix.translation.z,
00585          b1 = vectorToCenterWorld.x,
00586          b2 = vectorToCenterWorld.y,
00587          b3 = vectorToCenterWorld.z;
00588   
00589   pointOnField.x = int((a1 * b3 - a3 * b1) / b3 + 0.5);
00590   pointOnField.y = int((a2 * b3 - a3 * b2) / b3 + 0.5);
00591 
00592   return abs(pointOnField.x) < 10000 && abs(pointOnField.y) < 10000;
00593 }
00594 
00595 bool Geometry::calculatePointOnField
00596 (
00597  const int x,
00598  const int y,
00599  const CameraMatrix& cameraMatrix,
00600  const CameraMatrix& prevCameraMatrix,
00601  const CameraInfo& cameraInfo,
00602  Vector2<int>& pointOnField
00603  )
00604 {
00605   if(cameraInfo.simulated)
00606     return calculatePointOnField(x, y, cameraMatrix, cameraInfo, pointOnField);
00607   else
00608   {
00609     Vector2<int> pointOnField2;
00610     if(calculatePointOnField(x, y, cameraMatrix, cameraInfo, pointOnField) &&
00611        calculatePointOnField(x, y, prevCameraMatrix, cameraInfo, pointOnField2))
00612     {
00613       double scaleFactor = calculateScaleFactor(y, cameraMatrix.frameNumber, prevCameraMatrix.frameNumber, cameraInfo);
00614       
00615       pointOnField.x += int((pointOnField2.x - pointOnField.x) * scaleFactor);
00616       pointOnField.y += int((pointOnField2.y - pointOnField.y) * scaleFactor);
00617       return true;
00618     }
00619     else
00620       return false;
00621   }
00622 }
00623 
00624 void Geometry::calculatePointInImage
00625 ( 
00626  const Vector2<int>& point,
00627  const CameraMatrix& cameraMatrix,
00628  const CameraInfo& cameraInfo,
00629  Vector2<int>& pointInImage
00630  )
00631 {
00632   Vector2<double> offset(point.x - cameraMatrix.translation.x,
00633                          point.y - cameraMatrix.translation.y);
00634   calculatePointByAngles(
00635     Vector2<double>(atan2(offset.y,offset.x),
00636                     -atan2(cameraMatrix.translation.z,offset.abs())),
00637     cameraMatrix, cameraInfo, 
00638     pointInImage
00639   );
00640 }
00641 
00642 
00643 
00644 
00645 
00646 
00647 
00648 
00649 
00650 
00651 
00652 
00653 
00654 
00655 
00656 
00657 
00658 
00659 
00660 
00661 
00662 
00663 
00664 bool Geometry::getIntersectionPointsOfLineAndRectangle(
00665  const Vector2<int>& bottomLeft, 
00666  const Vector2<int>& topRight,
00667  const Geometry::Line line,
00668  Vector2<int>& point1, 
00669  Vector2<int>& point2
00670 )
00671 {
00672   int foundPoints=0;
00673   Vector2<double> point[2];
00674   if (line.direction.x!=0)
00675   {
00676     double y1=line.base.y+(bottomLeft.x-line.base.x)*line.direction.y/line.direction.x;
00677     if ((y1>=bottomLeft.y)&&(y1<=topRight.y))
00678     {
00679       point[foundPoints].x=bottomLeft.x;
00680       point[foundPoints++].y=y1;
00681     }
00682     double y2=line.base.y+(topRight.x-line.base.x)*line.direction.y/line.direction.x;
00683     if ((y2>=bottomLeft.y)&&(y2<=topRight.y))
00684     {
00685       point[foundPoints].x=topRight.x;
00686       point[foundPoints++].y=y2;
00687     }
00688   }
00689   if (line.direction.y!=0)
00690   {
00691     double x1=line.base.x+(bottomLeft.y-line.base.y)*line.direction.x/line.direction.y;
00692     if ((x1>=bottomLeft.x)&&(x1<=topRight.x)&&(foundPoints<2))
00693     {
00694       point[foundPoints].x=x1;
00695       point[foundPoints].y=bottomLeft.y;
00696       if ((foundPoints==0)||((point[0]-point[1]).abs()>0.1))
00697       {
00698         foundPoints++;
00699       }
00700     }
00701     double x2=line.base.x+(topRight.y-line.base.y)*line.direction.x/line.direction.y;
00702     if ((x2>=bottomLeft.x)&&(x2<=topRight.x)&&(foundPoints<2))
00703     {
00704       point[foundPoints].x=x2;
00705       point[foundPoints].y=topRight.y;
00706       if ((foundPoints==0)||((point[0]-point[1]).abs()>0.1))
00707       {
00708         foundPoints++;
00709       }
00710     }
00711   }
00712   switch (foundPoints)
00713   {
00714   case 1:
00715     point1.x=(int)point[0].x;
00716     point2.x=point1.x;
00717     point1.y=(int)point[0].y;
00718     point2.y=point1.y;
00719     foundPoints++;
00720     return true;
00721   case 2:
00722     if ((point[1]-point[0])*line.direction >0)
00723     {
00724       point1.x=(int)point[0].x;
00725       point1.y=(int)point[0].y;
00726       point2.x=(int)point[1].x;
00727       point2.y=(int)point[1].y;
00728     }
00729     else
00730     {
00731       point1.x=(int)point[1].x;
00732       point1.y=(int)point[1].y;
00733       point2.x=(int)point[0].x;
00734       point2.y=(int)point[0].y;
00735     }
00736     return true;
00737   default:
00738     return false;
00739   }
00740 }
00741 
00742 bool Geometry::clipLineWithRectangleCohenSutherland
00743 (
00744  const Vector2<int>& bottomLeft, 
00745  const Vector2<int>& topRight,
00746  Vector2<int>& point1, 
00747  Vector2<int>& point2
00748  )
00749 {
00750 
00751 
00752 
00753   int swap = 0;
00754 
00755   Vector2<int> p;
00756   int c1 = cohenSutherlandOutCode(bottomLeft, topRight, point1);
00757   int c2 = cohenSutherlandOutCode(bottomLeft, topRight, point2);
00758   
00759   if(c1 == 0 && c2 == 0) return false;
00760 
00761   while ( ( !(c1 == 0) || !(c2 == 0) ) && ( (c1&c2) == 0 ) ) 
00762   {
00763     if ( c1 == 0 ) 
00764     {
00765       p = point1;
00766       point1 = point2;
00767       point2 = p;
00768       c1 = c2; 
00769       swap++;
00770     }
00771     if (c1 & 1) 
00772     {
00773       point1.y = intersection(point1.x,point1.y,point2.x,point2.y,bottomLeft.x) ;
00774       point1.x = bottomLeft.x ; 
00775     }
00776     else if (c1&2)
00777     {
00778       point1.y = intersection(point1.x,point1.y,point2.x,point2.y,topRight.x) ;
00779       point1.x = topRight.x ; 
00780     }
00781     else if (c1&4)
00782     {
00783       point1.x = intersection(point1.y,point1.x,point2.y,point2.x,bottomLeft.y) ;
00784       point1.y = bottomLeft.y ; 
00785     }
00786     else if (c1&8)
00787     {
00788       point1.x = intersection(point1.y,point1.x,point2.y,point2.x,topRight.y) ;
00789       point1.y = topRight.y ; 
00790     }
00791     c1 = cohenSutherlandOutCode(bottomLeft, topRight, point1);
00792     c2 = cohenSutherlandOutCode(bottomLeft, topRight, point2);
00793   }
00794   if ( c1 == 0 && c2 == 0 )
00795   {
00796 
00797 
00798 
00799 
00800 
00801 
00802 
00803     if(swap % 2 == 1)
00804     {
00805       p = point1 ;
00806       point1 = point2;
00807       point2 = p ;
00808     }
00809     return true;
00810   }
00811   else
00812     return false;
00813 }
00814 
00815 int Geometry::intersection(int a1, int b1, int a2, int b2, int value)
00816 {
00817   int result = 0 ;
00818   if ( a2 - a1 != 0 )
00819     result = (int) (b1 +(double) (value-a1) / (a2-a1) * (b2-b1));
00820   else
00821     result = 32767;
00822   return(result);
00823 }
00824 
00825 Vector2<double> Geometry::relative2FieldCoord(RobotPose rp, double x, double y)
00826 {
00827   Vector3<double> relativePos(x, y, 0.0);
00828   Vector2<double> fieldPos(0.0, 0.0);
00829   RotationMatrix R;          
00830 
00831   R.fromKardanRPY(0,0, -rp.rotation);
00832   relativePos = R * relativePos;
00833 
00834   fieldPos.x = relativePos.x + rp.translation.x;
00835   fieldPos.y = relativePos.y + rp.translation.y;
00836   
00837   return fieldPos;
00838 }
00839 
00840 Vector2<double> Geometry::fieldCoord2Relative(RobotPose robotPose, Vector2<double> fieldCoord)
00841 {
00842   Vector2<double> relativeCoord;
00843   double distance = Geometry::distanceTo(robotPose.getPose(), fieldCoord);
00844   relativeCoord.x = distance * cos(Geometry::angleTo(robotPose.getPose(), fieldCoord));
00845   relativeCoord.y = distance * sin(Geometry::angleTo(robotPose.getPose(), fieldCoord));
00846   return relativeCoord;
00847 }
00848 
00849 
00850 bool Geometry::calculateBallInImage(const Vector2<double>& ballOffset,
00851                                     const CameraMatrix& cameraMatrix, const CameraInfo& cameraInfo, Circle& circle)
00852 {
00853   Vector2<double> offset(ballOffset.x - cameraMatrix.translation.x,
00854                          ballOffset.y - cameraMatrix.translation.y);
00855   double distance = offset.abs(),
00856          height = cameraMatrix.translation.z - ballRadius,
00857          cameraDistance = sqrt(sqr(distance) + sqr(height));
00858   circle.center = Vector2<double>(atan2(offset.y,offset.x),-atan2(height,distance));
00859   if(cameraDistance >= ballRadius)
00860   {
00861     double alpha = pi_2 - circle.center.y - acos(ballRadius / cameraDistance),
00862            yBottom = -atan2(height + cos(alpha) * ballRadius,
00863                             distance - sin(alpha) * ballRadius),
00864            beta = pi_2 - circle.center.y + acos(ballRadius / cameraDistance),
00865            yTop = -atan2(height + cos(beta) * ballRadius,
00866                          distance - sin(beta) * ballRadius);
00867     Vector2<int> top,
00868                  bottom;
00869     calculatePointByAngles(Vector2<double>(circle.center.x,yTop),cameraMatrix, cameraInfo, top);
00870     calculatePointByAngles(Vector2<double>(circle.center.x,yBottom),cameraMatrix, cameraInfo, bottom);
00871     circle.center.x = (top.x + bottom.x) / 2.0;
00872     circle.center.y = (top.y + bottom.y) / 2.0;
00873     circle.radius = (top - bottom).abs() / 2.0;
00874     return true;
00875   }
00876   else
00877     return false;
00878 }
00879 
00880 double Geometry::angleSizeToPixelSize(double angleSize, const CameraInfo& cameraInfo)
00881 {
00882   return cameraInfo.focalLength * tan(angleSize);
00883 }
00884 
00885 double Geometry::pixelSizeToAngleSize(double pixelSize, const CameraInfo& cameraInfo)
00886 {
00887   return atan(pixelSize * cameraInfo.focalLengthInv);  
00888 }
00889 
00890 double Geometry::getDistanceBySize
00891 (
00892  const CameraInfo& cameraInfo,
00893  double sizeInReality,
00894  double sizeInPixels
00895  )
00896 {
00897   double xFactor = cameraInfo.focalLength;
00898   return sizeInReality * xFactor / (sizeInPixels + 0.0001);
00899 }
00900 
00901 double Geometry::getDistanceBySize
00902 (
00903  const CameraInfo& cameraInfo,
00904  double sizeInReality,
00905  double sizeInPixels,
00906  int centerX,
00907  int centerY
00908  )
00909 {
00910   double mx = centerX;
00911   double my = centerY;
00912   double cx = cameraInfo.opticalCenter.x;
00913   double cy = cameraInfo.opticalCenter.y;
00914   double focalLenPow2 = cameraInfo.focalLenPow2;
00915   double sqrImgRadius = (mx-cx)*(mx-cx) + (my-cy)*(my-cy);
00916   double imgDistance = sqrt(focalLenPow2 + sqrImgRadius);
00917   return imgDistance*sizeInReality/(sizeInPixels + 0.0001);
00918 }
00919 
00920 double Geometry::getDistanceByAngleSize
00921 (
00922  double sizeInReality,
00923  double sizeAsAngle
00924  )
00925 {
00926   return (sizeInReality / 2.0) / tan(sizeAsAngle / 2.0 + 0.0001);
00927 }
00928 
00929 double Geometry::getBallDistanceByAngleSize
00930 (
00931  double sizeInReality,
00932  double sizeAsAngle
00933  )
00934 {
00935   return (sizeInReality / 2.0) / sin(sizeAsAngle / 2.0 + 0.0001);
00936 }
00937 
00938 double Geometry::getSizeByDistance
00939 (
00940  const CameraInfo& cameraInfo,
00941  double sizeInReality,
00942  double distance
00943 )
00944 {
00945   double xFactor = cameraInfo.focalLength;
00946   return sizeInReality / distance * xFactor;
00947 }
00948 
00949 
00950 double Geometry::getSizeByDistance
00951 (
00952  double sizeInReality,
00953  double distance,
00954  double imageWidthPixels,
00955  double imageWidthAngle
00956 )
00957 {
00958   double xFactor = imageWidthPixels / tan(imageWidthAngle / 2.0) / 2.0;
00959 
00960   return sizeInReality / distance * xFactor;
00961 }
00962 
00963 Geometry::Line Geometry::calculateHorizon
00964 (
00965 const CameraMatrix& cameraMatrix,
00966 const CameraInfo& cameraInfo
00967 )
00968 {
00969   Line horizon;
00970   double r31 = cameraMatrix.rotation.c[0].z;
00971   double r32 = cameraMatrix.rotation.c[1].z;
00972   double r33 = cameraMatrix.rotation.c[2].z;
00973   
00974   if(r33 == 0) 
00975     r33 = 0.00001;
00976   
00977   double x1 = 0,
00978          x2 = cameraInfo.resolutionWidth - 1,
00979          v1 = cameraInfo.focalLength,
00980          v2 = cameraInfo.opticalCenter.x,
00981          v3 = cameraInfo.opticalCenter.y,
00982          y1 = (v3 * r33 + r31 * v1 + r32 * v2) / r33,
00983          y2 = (v3 * r33 + r31 * v1 - r32 * v2) / r33;
00984   
00985   
00986   if((cameraMatrix.rotation * Vector3<double>(0,0,1)).z < 0)
00987   {
00988     double t = x1;
00989     x1 = x2;
00990     x2 = t;
00991     t = y1;
00992     y1 = y2;
00993     y2 = t;
00994   }
00995 
00996   horizon.base.x = (x1 + x2) / 2.0;
00997   horizon.base.y = (y1 + y2) / 2.0;
00998   horizon.direction.x = x2 - x1;
00999   horizon.direction.y = y2 - y1;
01000   horizon.normalizeDirection();
01001   return horizon;
01002 }
01003 
01004 
01005 int Geometry::calculateLineSize
01006 (
01007  const Vector2<int>& pointInImage, 
01008  const CameraMatrix& cameraMatrix,
01009  const CameraInfo& cameraInfo
01010  )
01011 {
01012   Vector2<int> pointOnField; 
01013   if(Geometry::calculatePointOnField(pointInImage.x, pointInImage.y, cameraMatrix, cameraInfo, pointOnField))
01014   {
01015     int distance = (int) sqrt(sqr(cameraMatrix.translation.z) + sqr(pointOnField.abs()));
01016     return (int)Geometry::getSizeByDistance(cameraInfo, 25, distance);
01017   }
01018   else
01019   {
01020     return 0;
01021   }
01022 }
01023 
01024 Geometry::CorrectedCoords Geometry::radialCorrectionLUT[cameraResolutionHeight_ERS7][cameraResolutionWidth_ERS7];
01025 
01026 void Geometry::setupRadialCorrection(const CameraInfo& cameraInfo)
01027 {
01028   double corrX, corrY;
01029   unsigned char cX, cY;
01030   for(int x=0; x<cameraInfo.resolutionWidth; x++)
01031     for(int y=0; y<cameraInfo.resolutionHeight; y++)
01032     {
01033       radialDistortionCorrection(cameraInfo, x, y, corrX, corrY);
01034       cX = (unsigned char) (corrX+0.5);
01035       cY = (unsigned char) (corrY+0.5);
01036       radialCorrectionLUT[y][x].x = cX;
01037       radialCorrectionLUT[y][x].y = cY;
01038     }
01039 }
01040 
01041 
01042 
01043 
01044 
01045 
01046 
01047 
01048 
01049 
01050 
01051 
01052 
01053 
01054 
01055 
01056 
01057 
01058 
01059 
01060 
01061 
01062 
01063 
01064 
01065 
01066 
01067 
01068 
01069 
01070 
01071 
01072 
01073 
01074 
01075 
01076 
01077 
01078 
01079 
01080 
01081 
01082 
01083 
01084 
01085 
01086 
01087 
01088 
01089 
01090 
01091 
01092 
01093 
01094 
01095 
01096 
01097 
01098 
01099 
01100 
01101 
01102 
01103 
01104 
01105 
01106 
01107 
01108 
01109 
01110 
01111 
01112 
01113 
01114 
01115 
01116 
01117 
01118 
01119 
01120 
01121 
01122 
01123 
01124 
01125 
01126 
01127 
01128 
01129 
01130 
01131 
01132 
01133 
01134 
01135 
01136 
01137 
01138 
01139 
01140 
01141 
01142 
01143 
01144 
01145 
01146 
01147 
01148 
01149 
01150 
01151 
01152 
01153 
01154 
01155 
01156 
01157 
01158 
01159 
01160 
01161 
01162 
01163 
01164 
01165 
01166 
01167 
01168 
01169 
01170 
01171 
01172 
01173 
01174 
01175 
01176 
01177 
01178 
01179 
01180 
01181 
01182 
01183 
01184 
01185 
01186 
01187 
01188 
01189 
01190 
01191 
01192 
01193 
01194 
01195 
01196 
01197 
01198 
01199 
01200 
01201 
01202 
01203 
01204 
01205 
01206 
01207 
01208 
01209 
01210 
01211 
01212 
01213 
01214 
01215 
01216 
01217 
01218 
01219 
01220 
01221 
01222 
01223 
01224 
01225 
01226 
01227 
01228 
01229 
01230 
01231 
01232 
01233 
01234 
01235 
01236 
01237 
01238 
01239 
01240 
01241 
01242 
01243 
01244 
01245 
01246 
01247 
01248 
01249 
01250 
01251 
01252 
01253 
01254 
01255 
01256 
01257 
01258 
01259 
01260 
01261 
01262 
01263 
01264 
01265 
01266 
01267 
01268 
01269 
01270 
01271 
01272 
01273 
01274 
01275 
01276 
01277 
01278 
01279 
01280 
01281 
01282 
01283 
01284 
01285 
01286 
01287 
01288 
01289 
01290 
01291 
01292 
01293 
01294 
01295 
01296 
01297 
01298 
01299 
01300 
01301 
01302 
01303 
01304 
01305 
01306 
01307 
01308 
01309 
01310 
01311 
01312 
01313 
01314 
01315 
01316 
01317 
01318 
01319 
01320 
01321 
01322 
01323