urgIntersection.cpp

00001 /*
00002   交点を求める計算
00003   いずれ、置き換える
00004 
00005   Satofumi KAMIMURA
00006   $Id$
00007 */
00008 
00009 #include "urgIntersection.h"
00010 
00011 using namespace VXV;
00012 
00013 static const double ERROR_VALUE = 10.0;
00014 
00015 typedef CoordinateCtrl::polygon_t crd_polygon_t;
00016 
00022 typedef struct {
00023   double a;                     
00024   double b;                     
00025   double c;                     
00026 } lineParam_t;
00027 
00028 
00029 // 2点を通る直線(ax + by + c = 0)を作成する
00030 static void createLine(lineParam_t *line,
00031                        const Grid& p0,  const Grid& p1) {
00032   line->a = p1.y - p0.y;
00033   line->b = p0.x - p1.x;
00034   line->c = -line->a * p0.x - line->b * p0.y;
00035 }
00036 
00037 
00038 // 点が直線上にあるかの判定を行う
00039 static bool onLine(const Grid& p0, const Grid& p1, double x, double y) {
00040   double large[2] = { p0.x, p0.y };
00041   double small[2] = { p1.x, p1.y };
00042   double value[2] = { x, y };
00043 
00044   for (int i = 0; i <= 1; ++i) {
00045     if (large[i] < small[i]) {
00046       double tmp = large[i];
00047       large[i] = small[i];
00048       small[i] = tmp;
00049     }
00050     if ((value[i] < small[i]) || (value[i] > large[i])) {
00051       return false;
00052     }
00053   }
00054   return true;
00055 }
00056 
00057 
00058 // 2直線の交点を求め、ある点からの距離を返す
00059 static int calcLength(const Grid& p0, const Grid& p1,
00060                       const Grid& p2, const Grid& p3,
00061                       const Grid& from) {
00062   lineParam_t line1, line2;
00063   createLine(&line1, p0, p1);
00064   createLine(&line2, p2, p3);
00065 
00066   double t = line1.b * line2.a - line2.b * line1.a;
00067   if (fabs(t) < 0.00001) {
00068     return INT_MAX;             // 2直線は平行
00069   }
00070   double x = (line1.c * line2.b - line2.c * line1.b) / t;
00071   double y = (line1.a * line2.c - line2.a * line1.c) / t;
00072 
00073   if (!onLine(p0, p1, x, y) || !onLine(p2, p3, x, y)) {
00074     return INT_MAX;             // データが線分上にない
00075   }
00076   return (int)sqrt((x - from.x)*(x - from.x) + (y - from.y)*(y - from.y));
00077 }
00078 
00079 
00080 int getLengthToEnvironment(const CoordinateCtrl::line_t& line,
00081                            const std::vector<crd_polygon_t>& polygons) {
00082   double angle = line.position.zt.to_rad();
00083   Grid p0(line.position.x, line.position.y);
00084   Grid p1(line.position.x + (int)(line.length * cos(angle)),
00085                line.position.y + (int)(line.length * sin(angle)));
00086 
00087   int length_min = line.length;
00088   for (std::vector<crd_polygon_t>::const_iterator lines = polygons.begin();
00089        lines != polygons.end(); ++lines) {
00090     Grid p2 = (*lines).back();
00091     for (unsigned int i = 0; i < lines->size(); ++i) {
00092       //地図上の直線を作成
00093       Grid p3((*lines)[i].x, (*lines)[i].y);
00094 
00095       // 2直線の交点を求める
00096       int length = 0;
00097       if ((length = calcLength(&p0, &p1, &p2, &p3, &p0)) >= 0) {
00098         // 現在までの最短距離と比較して保持
00099         if (length < length_min) {
00100           length_min = length;
00101         }
00102       }
00103       p2 = p3;
00104     }
00105   }
00106 
00107   // 誤差を乗せる
00108   if (length_min + ERROR_VALUE < line.length) {
00109     length_min
00110       += (int)(2.0 * ERROR_VALUE * rand()/(RAND_MAX+1.0) - ERROR_VALUE);
00111   }
00112   return length_min;
00113 }
00114 

Generated on Mon Apr 13 22:52:03 2009 by  doxygen 1.5.7.1