00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "mlib/points.H"
00010
00011 using namespace mlib;
00012
00013 CWtransf mlib::Identity;
00014
00015 CWvec mlib::Wvec::_null_vec(0,0,0);
00016 CWvec mlib::Wvec::_x_axis(1,0,0);
00017 CWvec mlib::Wvec::_y_axis(0,1,0);
00018 CWvec mlib::Wvec::_z_axis(0,0,1);
00019
00020 CWpt mlib::Wpt::_origin;
00021
00022 CXYvec mlib::XYvec::_null_vec(0,0);
00023 CXYvec mlib::XYvec::_x_axis(1,0);
00024 CXYvec mlib::XYvec::_y_axis(0,1);
00025
00026 CXYpt mlib::XYpt::_origin;
00027
00028 CNDCZvec mlib::NDCZvec::_null_vec(0,0,0);
00029 CNDCZvec mlib::NDCZvec::_x_axis(1,0,0);
00030 CNDCZvec mlib::NDCZvec::_y_axis(0,1,0);
00031 CNDCZvec mlib::NDCZvec::_z_axis(0,0,1);
00032
00033 CNDCZpt mlib::NDCZpt::_origin;
00034
00035 CNDCvec mlib::NDCvec::_null_vec(0,0);
00036 CNDCvec mlib::NDCvec::_x_axis(1,0);
00037 CNDCvec mlib::NDCvec::_y_axis(0,1);
00038
00039 CNDCpt mlib::NDCpt::_origin;
00040
00041 CVEXEL mlib::VEXEL::_null_vec(0,0);
00042 CVEXEL mlib::VEXEL::_x_axis(1,0);
00043 CVEXEL mlib::VEXEL::_y_axis(0,1);
00044
00045 CPIXEL mlib::PIXEL::_origin;
00046
00047 CUVvec mlib::UVvec::_null_vec(0,0);
00048 CUVvec mlib::UVvec::_u_dir(1,0);
00049 CUVvec mlib::UVvec::_v_dir(0,1);
00050
00051 CUVpt mlib::UVpt::_origin;
00052
00053
00054
00055
00056
00057 mlib::Wpt::Wpt(
00058 CXYpt &x,
00059 CWpt &pt
00060 )
00061 {
00062 *this = XYtoW_1(x, pt);
00063 }
00064
00065 mlib::Wpt::Wpt(
00066 CXYpt &x,
00067 double d
00068 )
00069 {
00070 *this = XYtoW_2(x, d);
00071 }
00072
00073 mlib::Wpt::Wpt(CNDCZpt &p)
00074 {
00075 Wpt ndc;
00076 ndc[0] = p[0];
00077 ndc[1] = p[1];
00078 ndc[2] = p[2];
00079
00080 *this = VIEW_NDC_TRANS().inverse() * ndc;
00081 }
00082
00083 mlib::Wpt::Wpt(CXYpt &x)
00084 {
00085 *this = XYtoW_3(x);
00086 }
00087
00088 mlib::Wvec::Wvec(CNDCZvec& v, CWtransf& obj_to_ndc_der_inv)
00089 {
00090
00091
00092
00093
00094
00095 Wvec temp(v[0],v[1],v[2]);
00096 *this = obj_to_ndc_der_inv * temp;
00097
00098 }
00099
00100 mlib::Wvec::Wvec(CXYpt &x)
00101 {
00102 *this = XYtoWvec(x);
00103 }
00104
00105 bool
00106 mlib::Wpt::in_frustum() const
00107 {
00108 return NDCZpt(*this).in_frustum();
00109 }
00110
00111 mlib::Wvec::Wvec(CWpt &p, CVEXEL &v)
00112 {
00113 Wpt p2(PIXEL(p)+v, p);
00114 *this = p2 - p;
00115 }
00116
00117
00118
00119 mlib::XYpt::XYpt(CWpt &w)
00120 {
00121 *this = WtoXY(w);
00122 }
00123
00124 mlib::XYpt::XYpt(CNDCpt &n)
00125 {
00126 double aspect = VIEW_ASPECT();
00127 if (aspect > 1) {
00128 _x = n[0] / aspect;
00129 _y = n[1];
00130 } else {
00131 _x = n[0];
00132 _y = n[1] * aspect;
00133 }
00134 }
00135
00136 mlib::XYvec::XYvec(CNDCvec &n)
00137 {
00138 double aspect = VIEW_ASPECT();
00139 if (aspect > 1) {
00140 _x = n[0] / aspect;
00141 _y = n[1];
00142 } else {
00143 _x = n[0];
00144 _y = n[1] * aspect;
00145 }
00146 }
00147
00148 mlib::XYpt::XYpt(CPIXEL &p)
00149 {
00150 NDCpt corner;
00151 int w, h; VIEW_SIZE (w, h);
00152 double zoom; VIEW_PIXELS(zoom, corner);
00153 XYpt botleft(corner);
00154
00155 _x = 2 * (p[0]/w -1);
00156 _y = 2 * (p[1]/h -1);
00157
00158
00159
00160
00161
00162 _x = (1/zoom) *_x - botleft[0];
00163 _y = (1/zoom) *_y - botleft[1];
00164 }
00165
00166 mlib::XYvec::XYvec(CVEXEL &v)
00167 {
00168 int w, h;
00169 VIEW_SIZE(w, h);
00170 _x = 2*v[0]/w;
00171 _y = 2*v[1]/h;
00172 }
00173
00174
00175
00176 bool
00177 mlib::NDCZpt::in_frustum() const
00178 {
00179
00180
00181
00182 if (!in_interval(_z, 0.0, 1.0)) {
00183 return 0;
00184 }
00185
00186
00187
00188 int w,h; VIEW_SIZE(w,h);
00189 double a = (double)h/(double)w;
00190 if (a > 1) {
00191
00192 return (in_interval(_y, -a, a) && in_interval(_x, -1.0, 1.0));
00193 } else {
00194
00195 assert(a > 1e-6);
00196 a = 1/a;
00197 return (in_interval(_x, -a, a) && in_interval(_y, -1.0, 1.0));
00198
00199 }
00200 }
00201
00202
00203 mlib::NDCpt::NDCpt(CXYpt &x)
00204 {
00205 double aspect = VIEW_ASPECT();
00206 if (aspect > 1) {
00207 _x = x[0] * aspect;
00208 _y = x[1];
00209 } else {
00210 assert(aspect > 1e-6);
00211 _x = x[0];
00212 _y = x[1] / aspect;
00213 }
00214 }
00215
00216 mlib::NDCvec::NDCvec(CXYvec &x)
00217 {
00218 double aspect = VIEW_ASPECT();
00219 if (aspect > 1) {
00220 _x = x[0] * aspect;
00221 _y = x[1];
00222 } else {
00223 _x = x[0];
00224 _y = x[1] / aspect;
00225 }
00226 }
00227
00228 mlib::NDCpt::NDCpt(CWpt &w)
00229 {
00230 *this = NDCZpt(w);
00231 }
00232
00233 mlib::NDCvec::NDCvec(CVEXEL &v)
00234 {
00235 int w, h;
00236 VIEW_SIZE(w, h);
00237
00238 double aspect = VIEW_ASPECT();
00239 if (aspect > 1) {
00240 _x = 2*v[0]*aspect/w;
00241 _y = 2*v[1]/h;
00242 } else {
00243 _x = 2*v[0]/w;
00244 _y = 2*v[1]/(aspect*h);
00245 }
00246 }
00247
00248
00249
00250 mlib::NDCZpt::NDCZpt(CWpt &p)
00251 {
00252 Wpt ndc = VIEW_NDC_TRANS() * p;
00253
00254 _x = ndc[0];
00255 _y = ndc[1];
00256 _z = ndc[2];
00257 }
00258
00259 mlib::NDCZpt::NDCZpt(CWpt& o, CWtransf& PM)
00260 {
00261
00262
00263
00264
00265
00266
00267
00268 Wpt ndc = PM * o;
00269
00270 _x = ndc[0];
00271 _y = ndc[1];
00272 _z = ndc[2];
00273 }
00274
00275 mlib::NDCZpt::NDCZpt(CXYpt &x)
00276 {
00277 _z = 0;
00278 double aspect = VIEW_ASPECT();
00279 if (aspect > 1) {
00280 _x = x[0]*aspect;
00281 _y = x[1];
00282 } else {
00283 _x = x[0];
00284 _y = x[1]/aspect;
00285 }
00286 }
00287
00288 mlib::NDCZpt::NDCZpt(CNDCpt &p)
00289 {
00290 _x = p[0];
00291 _y = p[1];
00292 _z = 0;
00293 }
00294
00295 mlib::NDCZpt::NDCZpt(CPIXEL &p)
00296 {
00297 int w, h;
00298 _z = 0;
00299 VIEW_SIZE(w, h);
00300 double aspect = VIEW_ASPECT();
00301 if (aspect > 1 ) {
00302 _x = (2*p[0]/w - 1) * aspect;
00303 _y = (2*p[1]/h - 1);
00304 } else {
00305 _x = (2*p[0]/w - 1);
00306 _y = (2*p[1]/h - 1) / aspect;
00307 }
00308 }
00309
00310 mlib::NDCZvec::NDCZvec(CNDCvec &v)
00311 {
00312 _x = v[0];
00313 _y = v[1];
00314 _z = 0;
00315 }
00316
00317 mlib::NDCZvec::NDCZvec(CXYvec &x)
00318 {
00319 _z = 0;
00320 double aspect = VIEW_ASPECT();
00321 if (aspect > 1) {
00322 _x = x[0]*aspect;
00323 _y = x[1];
00324 } else {
00325 _x = x[0];
00326 _y = x[1]/aspect;
00327 }
00328 }
00329
00330 mlib::NDCZvec::NDCZvec(CVEXEL &v)
00331 {
00332 int w, h;
00333 _z = 0;
00334 VIEW_SIZE(w, h);
00335 double aspect = VIEW_ASPECT();
00336 if (aspect > 1) {
00337 _x = 2*v[0]*aspect/w;
00338 _y = 2*v[1]/h;
00339 } else {
00340 _x = 2*v[0]/w;
00341 _y = 2*v[1]/(aspect*h);
00342 }
00343 }
00344
00345 mlib::NDCZvec::NDCZvec(CWvec&v, CWtransf& obj_to_ndc_der)
00346 {
00347
00348
00349
00350
00351
00352 Wvec temp = obj_to_ndc_der * v;
00353 _x = temp[0]; _y = temp[1]; _z = temp[2];
00354 }
00355
00356 NDCZvec
00357 mlib::normal_to_ndcz(CWpt& p, CWvec& world_normal)
00358 {
00359 Wvec temp = VIEW_NDC_TRANS().derivative(p) * world_normal;
00360 return NDCZvec(temp[0], temp[1], temp[2]);
00361 }
00362
00363
00364
00365 NDCZvec
00366 mlib::NDCZpt_list::tan(int i) const
00367 {
00368 NDCZpt *ar = _array;
00369 const int n=num()-1;
00370 if (i<0 || i>n || n<1) return NDCZvec();
00371 if (i==0) return (ar[1]-ar[ 0]).normalized();
00372 if (i==n) return (ar[n]-ar[n-1]).normalized();
00373 return ((ar[i+1]-ar[i]).normalized() + (ar[i]-ar[i-1]).normalized()).normalized();
00374 }
00375
00376
00377 NDCZpt
00378 mlib::NDCZpt_list::interpolate(double s, NDCZvec *tan, int*segp, double*tp) const
00379 {
00380 int seg;
00381 double t;
00382 interpolate_length(s, seg, t);
00383 const NDCZvec v = _array[seg+1]-_array[seg];
00384 if (tan) *tan = v.normalized();
00385 if (segp) *segp = seg;
00386 if (tp) *tp = t;
00387
00388 return _array[seg]+v*t;
00389 }
00390
00391 void
00392 mlib::NDCZpt_list::interpolate_length(double s, int &seg, double &t) const
00393 {
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 if (_partial_length.num() != _num) {
00406 cerr << "NDCZpt_list::interpolate_length: "
00407 << "Warning: partial lengths are out of date."
00408 << endl;
00409
00410 ((NDCZpt_list*)this)->update_length();
00411 }
00412
00413 const double val = s*length();
00414 if (val <= 0) {
00415 seg = 0;
00416 t = 0;
00417 return;
00418 }
00419 if (val >= length()) {
00420 seg = _num-2;
00421 t = 1;
00422 return;
00423 }
00424
00425 int l=0, r=_num-1, m;
00426 while ((m = (l+r) >> 1) != l) {
00427 if (val < _partial_length[m])
00428 r = m;
00429 else l = m;
00430 }
00431 seg = m;
00432 t = (val-_partial_length[m])/(_partial_length[m+1]-_partial_length[m]);
00433 }
00434
00435 NDCpt_list&
00436 mlib::NDCpt_list::operator=(CPIXEL_list& P)
00437 {
00438 clear();
00439 for (int i=0; i<P.num(); i++)
00440 add(NDCpt(P[i]));
00441 update_length();
00442 return *this;
00443 }
00444
00445 NDCpt_list&
00446 mlib::NDCpt_list::operator=(CXYpt_list& X)
00447 {
00448 clear();
00449 for (int i=0; i<X.num(); i++)
00450 add(NDCpt(X[i]));
00451 update_length();
00452 return *this;
00453 }
00454
00455 NDCpt_list&
00456 mlib::NDCpt_list::operator=(CNDCZpt_list& N)
00457 {
00458 clear();
00459 for (int i=0; i<N.num(); i++)
00460 add(NDCpt(N[i]));
00461 update_length();
00462 return *this;
00463 }
00464
00465
00466 mlib::VEXEL::VEXEL(CNDCvec &n)
00467 {
00468 int w, h;
00469 VIEW_SIZE(w, h);
00470 double aspect = VIEW_ASPECT();
00471 if (aspect > 1) {
00472 _x = n[0]/(aspect/w)/2;
00473 _y = n[1]*h/2;
00474 } else {
00475 _x = n[0]*w/2;
00476 _y = n[1]*(aspect*h)/2;
00477 }
00478 }
00479
00480
00481 mlib::VEXEL::VEXEL(CWpt &wp, CWvec &wv)
00482 {
00483 PIXEL p1(wp), p2(wp + wv);
00484 *this = p2 - p1;
00485 }
00486
00487 mlib::PIXEL::PIXEL(CXYpt &x)
00488 {
00489 NDCpt corner;
00490 int w,h; VIEW_SIZE (w, h);
00491 double zoom; VIEW_PIXELS(zoom, corner);
00492 XYpt botleft(corner);
00493
00494
00495 _x = w/2*(x[0] + botleft[0]);
00496 _y = h/2*(x[1] + botleft[1]);
00497
00498
00499 _x = _x*zoom + w;
00500 _y = _y*zoom + h;
00501 }
00502
00503
00504 mlib::VEXEL::VEXEL(CXYvec &x)
00505 {
00506 int w, h; VIEW_SIZE(w, h);
00507
00508 _x = x[0]*w/2.;
00509 _y = x[1]*h/2.;
00510 }
00511
00512 PIXEL_list&
00513 mlib::PIXEL_list::operator=(CWpt_list& X)
00514 {
00515 clear();
00516 for (int i=0; i<X.num(); i++)
00517 add(PIXEL(X[i]));
00518 update_length();
00519 return *this;
00520 }
00521
00522 PIXEL_list&
00523 mlib::PIXEL_list::operator=(CXYpt_list& X)
00524 {
00525 clear();
00526 for (int i=0; i<X.num(); i++)
00527 add(PIXEL(X[i]));
00528 update_length();
00529 return *this;
00530 }
00531
00532 PIXEL_list&
00533 mlib::PIXEL_list::operator=(CNDCpt_list& N)
00534 {
00535 clear();
00536 for (int i=0; i<N.num(); i++)
00537 add(PIXEL(N[i]));
00538 update_length();
00539 return *this;
00540 }
00541
00542 PIXEL_list&
00543 mlib::PIXEL_list::operator=(CNDCZpt_list& N)
00544 {
00545 clear();
00546 for (int i=0; i<N.num(); i++)
00547 add(PIXEL(N[i]));
00548 update_length();
00549 return *this;
00550 }
00551
00552 bool
00553 mlib::Wpt_list::project(XYpt_list& ret) const
00554 {
00555
00556
00557
00558
00559 ret.clear();
00560
00561
00562
00563 if (empty())
00564 return 1;
00565
00566
00567 ret.realloc(_num);
00568
00569
00570
00571 for (int k=0; k<_num; k++) {
00572 NDCZpt ndcz = NDCZpt(_array[k]);
00573 if (!ndcz.in_frustum()) {
00574 ret.clear();
00575 return 0;
00576 }
00577 ret.add(NDCpt(ndcz));
00578 }
00579 return 1;
00580 }
00581
00582 bool
00583 mlib::Wpt_list::project(PIXEL_list& ret) const
00584 {
00585
00586
00587
00588 XYpt_list xy_list;
00589 if (!project(xy_list))
00590 return 0;
00591 ret = xy_list;
00592 return 1;
00593 }
00594
00595 int
00596 mlib::Wpt_list::closest_vertex(CPIXEL& p) const
00597 {
00598
00599
00600
00601
00602
00603
00604 int ret = -1;
00605 double min_d=0;
00606 for (int i=0; i<_num; i++) {
00607
00608 if (_array[i].in_frustum()) {
00609 double d = PIXEL(_array[i]).dist(p);
00610 if (ret < 0 || d < min_d) {
00611 min_d = d;
00612 ret = i;
00613 }
00614 }
00615 }
00616 return ret;
00617 }
00618
00619 bool
00620 mlib::Wpt_list::get_best_fit_plane(Wplane& P) const
00621 {
00622
00623
00624
00625
00626
00627
00628
00629 if (_num < 3)
00630 return 0;
00631
00632
00633 Wvec N;
00634 for (int k=0; k<_num; k++) {
00635 Wpt i = _array[k];
00636 Wpt j = _array[(k+1)%_num];
00637 N += Wvec(
00638 (i[1] - j[1])*(i[2] + j[2]),
00639 (i[2] - j[2])*(i[0] + j[0]),
00640 (i[0] - j[0])*(i[1] + j[1])
00641 );
00642 }
00643 N = N.normalized();
00644
00645
00646 if (N.is_null())
00647 return 0;
00648
00649
00650 P = Wplane(average(), N);
00651
00652 return 1;
00653 }
00654
00655
00656 bool
00657 mlib::Wpt_list::get_plane(Wplane &P, double len_scale) const
00658 {
00659
00660
00661
00662
00663
00664
00665 P = Wplane();
00666
00667
00668 Wplane ret;
00669 if (!get_best_fit_plane(ret))
00670 return 0;
00671
00672
00673
00674
00675
00676 if (_num != _partial_length.num()) {
00677 cerr << "Wpt_list::get_plane: Error: lengths are not updated" << endl;
00678 return 0;
00679 }
00680 double thresh = length()*len_scale;
00681 for (int k=0; k<_num; k++)
00682 if (ret.dist(_array[k]) > thresh)
00683 return 0;
00684
00685
00686 P = ret;
00687
00688 return 1;
00689 }
00690
00691