00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <cassert>
00022 #include "rtc/rtcGeometry2D.h"
00023 #include <rtc/rtcRotation2D.h>
00024
00025
00026 namespace rtc {
00027
00028
00029 #define INSIDE false
00030 #define OUTSIDE true
00031
00032 float dist2(const Vec2f &a, const Vec2f &b)
00033 {
00034 return (a-b).normSqr();
00035 }
00036
00037 float dist(const Vec2f &a, const Vec2f &b)
00038 {
00039 return (a-b).norm();
00040 }
00041
00042 void dist_to_line(const Vec2f &x, const Vec2f &a, const Vec2f &b, float &d, Vec2f &cp)
00043 {
00044 Vec2f ba(b[0]-a[0], b[1]-a[1]);
00045 Vec2f xa(x[0]-a[0], x[1]-a[1]);
00046
00047 float xa_ba = xa.dot(ba);
00048
00049 if (xa_ba < 0.0) {
00050 float nd = dist(x,a);
00051 cp = a;
00052 d = nd;
00053 return;
00054 }
00055
00056
00057
00058 float fact = xa_ba/ba.normSqr();
00059 if (fact >= 1.0) {
00060 float nd = dist(x,b);
00061 cp = b;
00062 d = nd;
00063 return;
00064 }
00065
00066
00067
00068 float nd = xa.normSqr() - xa_ba*fact;
00069 d = sqrt(nd);
00070 cp[0] = a[0] + fact * ba[0];
00071 cp[1] = a[1] + fact * ba[1];
00072 }
00073
00074 float dist_to_line(const Vec2f &x, const Vec2f &a, const Vec2f &b)
00075 {
00076 Vec2f ba(b[0]-a[0], b[1]-a[1]);
00077 Vec2f xa(x[0]-a[0], x[1]-a[1]);
00078
00079 float xa_ba = xa.dot(ba);
00080
00081 if (xa_ba < 0.0) {
00082 return dist(x,a);
00083 }
00084
00085
00086
00087 float fact = xa_ba/ba.normSqr();
00088 if (fact >= 1.0) {
00089 return dist(x,b);
00090 }
00091
00092
00093
00094 return sqrt(xa.normSqr() - xa_ba*fact);
00095 }
00096
00097 float proj_dist_to_line(const Vec2f &x, const Vec2f &a, const Vec2f &b)
00098 {
00099 Vec2f v(b[1]-a[1], a[0]-b[0]);
00100 v.normalize();
00101 Vec2f xa(x[0]-a[0], x[1]-a[1]);
00102 return abs(v.dot(xa));
00103 }
00104
00105
00106 bool closer_on_line(const Vec2f &x, const Vec2f &a, const Vec2f &b, float &d2, Vec2f &cp)
00107 {
00108 Vec2f ba(b[0]-a[0], b[1]-a[1]);
00109 Vec2f xa(x[0]-a[0], x[1]-a[1]);
00110
00111 float xa_ba = xa.dot(ba);
00112
00113 if (xa_ba < 0.0) {
00114 float nd = dist2(x, a);
00115 if (nd < d2) {
00116 cp = a;
00117 d2 = nd;
00118 return true;
00119 }
00120 return false;
00121 }
00122
00123
00124
00125 float fact = xa_ba/ba.normSqr();
00126 if (fact >= 1.0) {
00127 float nd = dist2(x,b);
00128 if (nd < d2) {
00129 cp = b;
00130 d2 = nd;
00131 return true;
00132 }
00133 return false;
00134 }
00135
00136
00137
00138 float nd = xa.normSqr() - xa_ba*fact;
00139 if (nd<0)
00140 nd=0.0f;
00141 if (nd < d2) {
00142 d2 = nd;
00143 cp[0] = a[0] + fact * ba[0];
00144 cp[1] = a[1] + fact * ba[1];
00145 return true;
00146 }
00147 return false;
00148 }
00149
00150
00151
00152 bool circle_within_bounds(const Vec2f &b, float r, const Vec2f &bc, float br)
00153 {
00154 r -= br;
00155 if ((b[0] - bc[0] <= r) ||
00156 (bc[0] - b[0] <= r) ||
00157 (b[1] - bc[1] <= r) ||
00158 (bc[1] - b[1] <= r)) return false;
00159 return true;
00160 }
00161
00162
00163
00164 bool circle_within_bounds(const Vec2f &b, float r, const Vec2f &min, const Vec2f &max)
00165 {
00166 if ((b[0] - min[0] <= r) ||
00167 (max[0] - b[0] <= r) ||
00168 (b[1] - min[1] <= r) ||
00169 (max[1] - b[1] <= r)) return false;
00170 return true;
00171 }
00172
00173
00174
00175 bool bounds_overlap_circle(const Vec2f &b, float r, const Vec2f &bc, float br)
00176 {
00177 float r2 = rtc_sqr(r);
00178 float R_max_x,R_max_y;
00179 float R_min_x,R_min_y;
00180
00181
00182 R_max_x = bc[0]+br-b[0]; R_max_y = bc[1]+br-b[1];
00183 R_min_x = bc[0]-br-b[0]; R_min_y = bc[1]-br-b[1];
00184
00185 if (R_max_x < 0)
00186 if ( R_max_y < 0)
00187 return ((R_max_x * R_max_x + R_max_y * R_max_y) < r2);
00188 else if ( R_min_y > 0)
00189 return ((R_max_x * R_max_x + R_min_y * R_min_y) < r2);
00190 else
00191 return(abs(R_max_x) < r);
00192 else if ( R_min_x > 0)
00193 if ( R_max_y < 0)
00194 return (( R_min_x * R_min_x + R_max_y * R_max_y) < r2);
00195 else if ( R_min_y > 0)
00196 return (( R_min_x * R_min_x + R_min_y * R_min_y) < r2);
00197 else
00198 return ( R_min_x < r);
00199 else
00200 if ( R_max_y < 0)
00201 return (abs(R_max_y) < r);
00202 else if ( R_min_y > 0)
00203 return ( R_min_y < r);
00204 else
00205 return(true);
00206 }
00207
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 long bevel_1d(const Vec2f &p)
00228 {
00229 long outcode = 0;
00230 if (p[0] > .5) outcode |= 0x01;
00231 if (p[0] < -.5) outcode |= 0x02;
00232 if (p[1] > .5) outcode |= 0x04;
00233 if (p[1] < -.5) outcode |= 0x08;
00234 return outcode;
00235 }
00236
00237
00238 long bevel_2d(const Vec2f &p)
00239 {
00240 long outcode = 0;
00241 if ( p[0] + p[1] > 1.0) outcode |= 0x01;
00242 if ( p[0] - p[1] > 1.0) outcode |= 0x02;
00243 if (-p[0] + p[1] > 1.0) outcode |= 0x04;
00244 if (-p[0] - p[1] > 1.0) outcode |= 0x08;
00245 return outcode;
00246 }
00247
00248
00249 Vec2f lerp(float t, const Vec2f &a, const Vec2f &b)
00250 {
00251 float v[2];
00252 float u = 1.0 - t;
00253 v[0]=u*a[0]+t*b[0];
00254 v[1]=u*a[1]+t*b[1];
00255 return Vec2f(v[0],v[1]);
00256 }
00257
00258
00259
00260
00261 bool point_on_edge(const Vec2f &p1, const Vec2f &p2, float alpha, long mask)
00262 {
00263 Vec2f line_point;
00264 line_point = lerp(alpha, p1, p2);
00265 long l = bevel_1d(line_point) & mask;
00266 return (l==0?INSIDE:OUTSIDE);
00267 }
00268
00269
00270
00271
00272
00273 bool segment_on_edge(const Vec2f &p1, const Vec2f &p2, long outcode_diff)
00274 {
00275 if (0x01 & outcode_diff)
00276 if (point_on_edge(p1,p2,( .5-p1[0])/(p2[0]-p1[0]),0xE) == INSIDE) return INSIDE;
00277 if (0x02 & outcode_diff)
00278 if (point_on_edge(p1,p2,(-.5-p1[0])/(p2[0]-p1[0]),0xD) == INSIDE) return INSIDE;
00279 if (0x04 & outcode_diff)
00280 if (point_on_edge(p1,p2,( .5-p1[1])/(p2[1]-p1[1]),0xB) == INSIDE) return INSIDE;
00281 if (0x08 & outcode_diff)
00282 if (point_on_edge(p1,p2,(-.5-p1[1])/(p2[1]-p1[1]),0x7) == INSIDE) return INSIDE;
00283 return OUTSIDE;
00284 }
00285
00286
00287
00288
00289
00290
00291
00292 bool line_outside_of_rect(const Vec2f &c, float s, const Vec2f &t1, const Vec2f &t2)
00293 {
00294
00295 long v1_test,v2_test;
00296
00297
00298
00299 Vec2f v1((t1[0]-c[0])/s, (t1[1]-c[1])/s);
00300 if (!(v1_test = bevel_1d(v1))) return INSIDE;
00301 Vec2f v2((t2[0]-c[0])/s, (t2[1]-c[1])/s);
00302 if (!(v2_test = bevel_1d(v2))) return INSIDE;
00303
00304
00305 if ((v1_test & v2_test) != 0) return OUTSIDE;
00306
00307
00308 v1_test |= bevel_2d(v1) << 8;
00309 v2_test |= bevel_2d(v2) << 8;
00310 if ((v1_test & v2_test) != 0) return OUTSIDE;
00311
00312
00313
00314
00315
00316
00317
00318 if (segment_on_edge(v1,v2,v1_test|v2_test) == INSIDE) return INSIDE;
00319
00320
00321
00322
00323
00324
00325
00326
00327 return OUTSIDE;
00328 }
00329
00330
00331
00332
00333 bool point_outside_of_rect(const Vec2f &c, float s, const Vec2f &p)
00334 {
00335 Vec2f v1((p[0]-c[0])/s, (p[1]-c[1])/s);
00336 if (!bevel_1d(v1)) return INSIDE;
00337 return OUTSIDE;
00338 }
00339
00340
00341
00342
00343
00344 bool point_outside_of_rect(const Vec2f &c, float xlen, float ylen, float rot_angle, const Vec2f &p)
00345 {
00346 Vec2f v(p[0]-c[0], p[1]-c[1]);
00347 Rotation2D<float> r(rot_angle);
00348 v=r*v;
00349 v.x[0]/=xlen;v.x[1]/=ylen;
00350 if (!bevel_1d(v)) return INSIDE;
00351 return OUTSIDE;
00352 }
00353
00354
00355
00356
00357
00358
00359 bool rect_rect_X(const Vec2f &c1, float theta1, float w1, float l1,
00360 const Vec2f &c2, float theta2, float w2, float l2) {
00361
00362 float x,y,sintheta2,costheta2;
00363 float tx, ty, scale_x, scale_y,sintheta1,costheta1;
00364 assert(l1);assert(w1);
00365 assert(l2);assert(w2);
00366
00367 sintheta2 = sin(theta2);
00368 costheta2 = cos(theta2);
00369
00370
00371 float rect2_x[4];
00372 float rect2_y[4];
00373
00374 x = -l2/2.0; y = -w2/2.0;
00375 rect2_x[0] = costheta2*(x) - sintheta2*(y) + c2[0];
00376 rect2_y[0] = sintheta2*(x) + costheta2*(y) + c2[1];
00377
00378 x = l2/2.0; y = -w2/2.0;
00379 rect2_x[1] = costheta2*(x) - sintheta2*(y) + c2[0];
00380 rect2_y[1] = sintheta2*(x) + costheta2*(y) + c2[1];
00381
00382 x = l2/2.0; y = w2/2.0;
00383 rect2_x[2] = costheta2*(x) - sintheta2*(y) + c2[0];
00384 rect2_y[2] = sintheta2*(x) + costheta2*(y) + c2[1];
00385
00386 x = -l2/2.0; y = w2/2.0;
00387 rect2_x[3] = costheta2*(x) - sintheta2*(y) + c2[0];
00388 rect2_y[3] = sintheta2*(x) + costheta2*(y) + c2[1];
00389
00390
00391 tx = c1[0];
00392 ty = c1[1];
00393 scale_x = l1;
00394 scale_y = w1;
00395 sintheta1 = sin(-theta1);
00396 costheta1 = cos(-theta1);
00397
00398 for(int i=0;i<4;++i) {
00399
00400 x = rect2_x[i] - tx;
00401 y = rect2_y[i] - ty;
00402 rect2_x[i] = (costheta1*(x) - sintheta1*(y))/scale_x;
00403 rect2_y[i] = (sintheta1*(x) + costheta1*(y))/scale_y;
00404 }
00405
00406 Vec2f t0(rect2_x[0], rect2_y[0]);
00407 Vec2f t1(rect2_x[1], rect2_y[1]);
00408 Vec2f t2(rect2_x[2], rect2_y[2]);
00409 Vec2f t3(rect2_x[3], rect2_y[3]);
00410
00411
00412 Vec2f c((float)0);
00413 bool boutside;
00414
00415 boutside = line_outside_of_rect(c, 1, t0, t1);
00416 if(!boutside) return true;
00417
00418 boutside = line_outside_of_rect(c, 1, t1, t2);
00419 if(!boutside) return true;
00420
00421 boutside = line_outside_of_rect(c, 1, t2, t3);
00422 if(!boutside) return true;
00423
00424 boutside = line_outside_of_rect(c, 1, t3, t0);
00425 if(!boutside) return true;
00426
00427 return false;
00428 }
00429
00430
00431
00432
00433
00434
00435
00436 bool line_rect_X(const Vec2f &t1, const Vec2f &t2,
00437 const Vec2f &c, float theta, float w, float l) {
00438 float x,y,sintheta,costheta;
00439 float tx, ty, scale_x, scale_y;
00440 Vec2f t1n,t2n;
00441 assert(l);assert(w);
00442
00443
00444 tx = c[0];
00445 ty = c[1];
00446 scale_x = l;
00447 scale_y = w;
00448 sintheta = sin(-theta);
00449 costheta = cos(-theta);
00450
00451
00452 x = t1[0] - tx;
00453 y = t1[1] - ty;
00454 t1n[0] = (costheta*(x) - sintheta*(y)) / scale_x;
00455 t1n[1] = (sintheta*(x) + costheta*(y)) / scale_y;
00456
00457
00458 x = t2[0] - tx;
00459 y = t2[1] - ty;
00460 t2n[0] = (costheta*(x) - sintheta*(y)) / scale_x;
00461 t2n[1] = (sintheta*(x) + costheta*(y)) / scale_y;
00462
00463
00464 Vec2f cn((float)0);
00465 bool boutside = line_outside_of_rect(cn, 1, t1n, t2n);
00466 if(!boutside) return true;
00467 return false;
00468 }
00469
00470
00471 }
00472