00001 #include "std/support.H"
00002 #include "disp/bbox.H"
00003 #include "disp/gel.H"
00004 #include "disp/ray.H"
00005 #include "disp/view.H"
00006
00007 using namespace mlib;
00008
00009 BBOX::BBOX(
00010 CGELptr &g,
00011 int recurse
00012 ) :_valid(true)
00013 {
00014 GELptr gel((GEL *)&*g);
00015 *this += BBOX(gel->bbox(recurse));
00016 }
00017
00018
00019
00020
00021 bool
00022 BBOX::points(
00023 Wpt_list& pts
00024 ) const
00025 {
00026 pts.clear();
00027 if (_valid) {
00028 pts.realloc(8);
00029 Wvec d = dim();
00030 Wvec dx(d[0], 0, 0);
00031 Wvec dy( 0, d[1], 0);
00032 Wvec dz( 0, 0, d[2]);
00033 pts += _min;
00034 pts += (_min + dx);
00035 pts += (_min + dy);
00036 pts += (_min + dz);
00037 pts += (_max - dx);
00038 pts += (_max - dy);
00039 pts += (_max - dz);
00040 pts += _max;
00041 }
00042 return _valid;
00043 }
00044
00045
00046
00047
00048 bool
00049 BBOX::intersects(
00050 CRAYhit &r,
00051 CWtransf &m
00052 ) const
00053 {
00054 if (!_valid) {
00055 err_msg("BBOX::intersects: BBOX is not valid");
00056 return 0;
00057 }
00058
00059 Wtransf m_inv = m.inverse();
00060 Wpt p = m_inv * r.point();
00061 Wvec d = m_inv * r.vec();
00062
00063
00064 if (fabs(d[0]) > 1e-8) {
00065 double qx = (d[0]<0) ? _min[0] : _max[0];
00066 double t = (qx - p[0])/d[0];
00067 Wpt h = p + d*t;
00068 if (_min[1]<=h[1] && _max[1]>=h[1] && _min[2]<=h[2] && _max[2]>=h[2])
00069 return 1;
00070 }
00071
00072 if (fabs(d[1]) > 1e-8) {
00073 double qy = (d[1]<0) ? _min[1] : _max[1];
00074 double t = (qy - p[1])/d[1];
00075 Wpt h = p + d*t;
00076 if (_min[0]<=h[0] && _max[0]>=h[0] && _min[2]<=h[2] && _max[2]>=h[2])
00077 return 1;
00078 }
00079
00080 if (fabs(d[2]) > 1e-8) {
00081 double qz = (d[2]<0) ? _min[2] : _max[2];
00082 double t = (qz - p[2])/d[2];
00083 Wpt h = p + d*t;
00084 if (_min[0]<=h[0] && _max[0]>=h[0] && _min[1]<=h[1] && _max[1]>=h[1])
00085 return 1;
00086 }
00087 return 0;
00088 }
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 bool
00103 BBOX::is_off_screen()
00104 {
00105
00106 if (!valid())
00107 return 0;
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 CCAMdataptr &camdata = VIEW::peek_cam_const()->data();
00153 CWpt& eye = camdata->from();
00154 Wpt o = center();
00155 Wvec v = o - eye;
00156 double R2 = dim().length_sqrd()/4;
00157 double L2 = v.length_sqrd();
00158 if (L2 <= R2)
00159 return 0;
00160
00161
00162
00163
00164
00165 double d = camdata->focal ();
00166 double x = camdata->width ()/2;
00167 double y = camdata->height()/2;
00168 double x2y2 = sqr(x) + sqr(y);
00169 double x2y2d2 = x2y2 + sqr(d);
00170 double R2L2 = R2/L2;
00171
00172
00173 double u = (camdata->at_v() * v)/sqrt(L2);
00174
00175
00176 return d*sqrt((1 - R2L2)/x2y2d2) > u + sqrt(R2L2*x2y2/x2y2d2);
00177 }
00178
00179 BBOX &
00180 BBOX::operator*=(
00181 CWtransf &x
00182 )
00183 {
00184 if (!valid())
00185 return *this;
00186
00187 Wpt_list pts(8);
00188 points(pts);
00189 pts.xform(x);
00190
00191 reset();
00192
00193 update(pts);
00194 return *this;
00195 }
00196
00197
00198
00199
00200 BBOX &
00201 BBOX::update(
00202 CWpt &p
00203 )
00204 {
00205 if (!_valid) {
00206 _min = p;
00207 _max = p;
00208 _valid = true;
00209 }
00210 else {
00211 for (int i=0;i<3;i++) {
00212 if (p[i] < _min[i]) _min[i] = p[i];
00213 if (p[i] > _max[i]) _max[i] = p[i];
00214 }
00215 }
00216
00217 return *this;
00218 }
00219
00220 BBOX &
00221 BBOX::update(
00222 CWpt_list &pts
00223 )
00224 {
00225 for (int j = 0; j < pts.num(); j++)
00226 update(pts[j]);
00227 return *this;
00228 }
00229
00230 void
00231 BBOX::ndcz_bounding_box(
00232 CWtransf &obj_to_ndc,
00233 NDCZpt& min_pt,
00234 NDCZpt& max_pt
00235 ) const
00236 {
00237 Wpt_list point_list;
00238 points(point_list);
00239
00240
00241 ARRAY<NDCZpt> ndcz_list;
00242 int i;
00243 for (i = 0; i < point_list.num(); i++) {
00244 ndcz_list += NDCZpt(point_list[i], obj_to_ndc);
00245 }
00246
00247
00248 int coord;
00249 for(coord = 0; coord < 3; coord++) {
00250 min_pt[coord] = 1e9;
00251 max_pt[coord] = -1e9;
00252 }
00253
00254
00255 for (i = 0; i < ndcz_list.num(); i++) {
00256 for (coord = 0; coord < 3; coord++) {
00257 if (ndcz_list[i][coord] < min_pt[coord])
00258 min_pt[coord] = ndcz_list[i][coord];
00259 else if (ndcz_list[i][coord] > max_pt[coord])
00260 max_pt[coord] = ndcz_list[i][coord];
00261 }
00262 }
00263 }
00264
00265
00266
00267
00268
00269 BBOX2D::BBOX2D(
00270 CGELptr &g,
00271 int recurse
00272 ) : _valid(true)
00273 {
00274 GELptr gel((GEL *)&*g);
00275 Wpt_list pts;
00276 gel->bbox(recurse).points(pts);
00277 for (int i = 0; i < pts.num(); i++)
00278 update(pts[i]);
00279 }
00280
00281 BBOX2D &
00282 BBOX2D::update(
00283 CXYpt &p
00284 )
00285 {
00286 if (!_valid) {
00287 _min = p;
00288 _max = p;
00289 _valid = true;
00290 }
00291 else {
00292 for (int i=0;i<2;i++) {
00293 if (p[i] < _min[i]) _min[i] = p[i];
00294 if (p[i] > _max[i]) _max[i] = p[i];
00295 }
00296 }
00297
00298 return *this;
00299 }
00300
00301 bool
00302 BBOX::contains(
00303 CWpt &p
00304 ) const
00305 {
00306 if (!_valid)
00307 return false;
00308 else
00309 return p[0] >= _min[0] && p[1] >= _min[1] && p[2] >= _min[2] &&
00310 p[0] <= _max[0] && p[1] <= _max[1] && p[2] <= _max[2];
00311 }
00312
00313 bool
00314 BBOX::overlaps(
00315 CBBOX &bbox
00316 ) const
00317 {
00318 if (!_valid)
00319 return false;
00320 else
00321 return (bbox.min()[0] <= max()[0] && bbox.max()[0] >= min()[0] &&
00322 bbox.min()[1] <= max()[1] && bbox.max()[1] >= min()[1] &&
00323 bbox.min()[2] <= max()[2] && bbox.max()[2] >= min()[2]);
00324 }
00325
00326
00327 bool
00328 BBOX2D::overlaps(
00329 CBBOX2D &bbox
00330 ) const
00331 {
00332 if (!_valid)
00333 return false;
00334 else
00335 return (bbox.min()[0] <= max()[0] && bbox.max()[0] >= min()[0] &&
00336 bbox.min()[1] <= max()[1] && bbox.max()[1] >= min()[1]);
00337 }
00338
00339 bool
00340 BBOX2D::contains(
00341 CXYpt &p
00342 ) const
00343 {
00344 if (!_valid)
00345 return false;
00346 else
00347 return p[0] >= _min[0] && p[1] >= _min[1] &&
00348 p[0] <= _max[0] && p[1] <= _max[1];
00349 }
00350
00351 double
00352 BBOX2D::dist(
00353 CXYpt &p
00354 ) const
00355 {
00356 if (!_valid)
00357 return -1;
00358 else {
00359 double dist = 1e9;
00360
00361 if (contains(p)) {
00362 dist = 0;
00363 } else {
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378 double h = dim()*XYvec(0,1);
00379 double w = dim()*XYvec(1,0);
00380
00381 XYpt a = _min + XYvec(0, h);
00382 XYpt b = _max;
00383 XYpt c = _min;
00384 XYpt d = _min + XYvec(w,0);
00385
00386 dist = ::min(dist, XYline(a,b).project_to_seg(p).dist(p));
00387 dist = ::min(dist, XYline(a,c).project_to_seg(p).dist(p));
00388 dist = ::min(dist, XYline(c,d).project_to_seg(p).dist(p));
00389 dist = ::min(dist, XYline(b,d).project_to_seg(p).dist(p));
00390 }
00391
00392 return dist;
00393 }
00394 }
00395
00396 BBOX2D &
00397 BBOX2D::operator+=(CXYpt_list &pts)
00398 {
00399 for (int i = 0; i < pts.num(); i++)
00400 (void) update(pts[i]);
00401 return *this;
00402 }
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 BBOXpix &
00413 BBOXpix::update(CPIXEL &p) {
00414 if (!_valid) {
00415 _min = p;
00416 _max = p;
00417 _valid = true;
00418 } else {
00419 for (int i=0;i<2;i++) {
00420 if (p[i] < _min[i]) _min[i] = p[i];
00421 if (p[i] > _max[i]) _max[i] = p[i];
00422 }
00423 }
00424
00425 return *this;
00426 }
00427
00428 bool
00429 BBOXpix::contains(CPIXEL &p) const {
00430 if (!_valid) {
00431 return false;
00432 } else {
00433 return (p[0] >= _min[0] && p[1] >= _min[1] &&
00434 p[0] <= _max[0] && p[1] <= _max[1]);
00435 }
00436 }
00437
00438 bool
00439 BBOXpix::overlaps(CBBOXpix &bbox) const {
00440 if (!_valid){
00441 return false;
00442 } else {
00443 return (bbox.min()[0] <= max()[0] && bbox.max()[0] >= min()[0] &&
00444 bbox.min()[1] <= max()[1] && bbox.max()[1] >= min()[1]);
00445 }
00446 }
00447
00448 double
00449 BBOXpix::dist(CPIXEL &p) const {
00450 if (!_valid) return -1;
00451
00452
00453 double dist = 1e9;
00454
00455 if (contains(p)) {
00456 dist = 0.0;
00457 } else {
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472 double h = height();
00473 double w = width();
00474
00475 PIXEL a = _min + VEXEL(0, h);
00476 PIXEL b = _max;
00477 PIXEL c = _min;
00478 PIXEL d = _min + VEXEL(w,0);
00479
00480 dist = ::min(dist, PIXELline(a,b).project_to_seg(p).dist(p));
00481 dist = ::min(dist, PIXELline(a,c).project_to_seg(p).dist(p));
00482 dist = ::min(dist, PIXELline(c,d).project_to_seg(p).dist(p));
00483 dist = ::min(dist, PIXELline(b,d).project_to_seg(p).dist(p));
00484 }
00485
00486 return dist;
00487 }
00488
00489
00490 BBOXpix &
00491 BBOXpix::operator+=(CPIXEL_list &pts) {
00492 for (int i = 0; i < pts.num(); i++)
00493 (void) update(pts[i]);
00494 return *this;
00495 }
00496