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