00001
00015 #ifndef _DLR_NUMERIC_AMANATIDESWOO2D_H_
00016 #define _DLR_NUMERIC_AMANATIDESWOO2D_H_
00017
00018 #include <iostream>
00019 #include <limits>
00020 #include <dlrCommon/exception.h>
00021 #include <dlrNumeric/vector2D.h>
00022 #include <dlrNumeric/transform2D.h>
00023 #include <dlrNumeric/utilities.h>
00024 #include <dlrNumeric/amanatidesWoo2DIterator.h>
00025
00026 namespace dlr {
00027
00028 namespace numeric {
00029
00079 template <class ARRAY2D>
00080 class AmanatidesWoo2D {
00081 public:
00082
00083
00091 typedef AmanatidesWoo2DIterator<ARRAY2D> iterator;
00092
00093
00094
00095
00096
00097
00098
00133 AmanatidesWoo2D(ARRAY2D& data,
00134 const Transform2D& pixelTworld,
00135 const Vector2D& rayOrigin,
00136 const Vector2D& rayDirection,
00137 bool downstreamOnly=true);
00138
00139
00147 AmanatidesWoo2D(const AmanatidesWoo2D& source);
00148
00153 ~AmanatidesWoo2D();
00154
00173 iterator
00174 begin();
00175
00186 iterator
00187 end();
00188
00195 ARRAY2D&
00196 getData() {return m_data;}
00197
00212 inline bool
00213 validIntersection();
00214
00223 AmanatidesWoo2D&
00224 operator=(const AmanatidesWoo2D& source);
00225
00226 private:
00227
00244 std::pair<double, double>
00245 findEntryAndExitPoints(const Vector2D& rayOriginPixel,
00246 const Vector2D& rayDirectionPixel,
00247 const ARRAY2D& data);
00248
00260 double
00261 findIntersection(const Vector2D& rayOrigin,
00262 const Vector2D& rayDirection,
00263 const Vector2D& bVector,
00264 double cConstant,
00265 double defaultValue);
00266
00269 ARRAY2D& m_data;
00270
00273 int m_initialU;
00274
00277 int m_initialV;
00278
00282 int m_stepU;
00283
00287 int m_stepV;
00288
00291 double m_tDeltaU;
00292
00295 double m_tDeltaV;
00296
00300 double m_tMaxU;
00301
00305 double m_tMaxV;
00306
00313 double m_tStart;
00314
00317 bool m_validIntersection;
00318 };
00319
00320 }
00321
00322 }
00323
00324
00325
00326
00327 namespace dlr {
00328
00329 using numeric::AmanatidesWoo2D;
00330
00331 }
00332
00333
00334
00335
00336
00337
00338 namespace dlr {
00339
00340 namespace numeric {
00341
00342 template <class ARRAY2D>
00343 AmanatidesWoo2D<ARRAY2D>::
00344 AmanatidesWoo2D(ARRAY2D& data,
00345 const Transform2D& pixelTworld,
00346 const Vector2D& rayOrigin,
00347 const Vector2D& rayDirection,
00348 bool downstreamOnly)
00349 : m_data(data),
00350 m_initialU(-1),
00351 m_initialV(-1),
00352
00353
00354 m_stepU(),
00355 m_stepV(),
00356 m_tDeltaU(),
00357 m_tDeltaV(),
00358 m_tMaxU(),
00359 m_tMaxV(),
00360 m_tStart(),
00361 m_validIntersection(true)
00362 {
00363
00364 Vector2D rayOriginPixel = pixelTworld * rayOrigin;
00365 Vector2D rayDirectionPixel =
00366 (pixelTworld * (rayOrigin + rayDirection)) - rayOriginPixel;
00367
00368
00369
00370
00371
00372
00373 std::pair<double, double> tEntry_tExit =
00374 this->findEntryAndExitPoints(rayOriginPixel, rayDirectionPixel, m_data);
00375
00376
00377
00378
00379
00380 if(downstreamOnly && (tEntry_tExit.first < 0.0)) {
00381 tEntry_tExit.first = 0.0;
00382 }
00383
00384
00385
00386
00387 if(tEntry_tExit.second <= tEntry_tExit.first) {
00388 m_validIntersection = false;
00389 return;
00390 }
00391
00392
00393 Vector2D entryPoint =
00394 rayOriginPixel + tEntry_tExit.first * rayDirectionPixel;
00395
00396
00397
00398 if(entryPoint.x() < 0.0) {
00399 entryPoint.x() = 0.0;
00400 }
00401 if(entryPoint.y() < 0.0) {
00402 entryPoint.y() = 0.0;
00403 }
00404
00405
00406
00407
00408
00409
00410 m_initialU = static_cast<int>(entryPoint.x());
00411 m_initialV = static_cast<int>(entryPoint.y());
00412
00413
00414
00415
00416
00417
00418
00419 if(m_initialU == static_cast<int>(m_data.columns())) {
00420 --m_initialU;
00421 }
00422 if(m_initialV == static_cast<int>(m_data.rows())) {
00423 --m_initialV;
00424 }
00425
00426
00427 if((m_initialU >= static_cast<int>(m_data.columns()))
00428 || (m_initialV >= static_cast<int>(m_data.rows()))) {
00429 DLR_THROW3(LogicException,
00430 "AmanatidesWoo2D::AmanatidesWoo2D(ARRAY2D&, ...)",
00431 "Illegal value for m_initialU or m_initialV.");
00432 }
00433
00434
00435 m_tStart = tEntry_tExit.first;
00436
00437
00438
00439
00440
00441 if(rayDirectionPixel.x() > 0.0) {
00442 m_stepU = 1;
00443 m_tDeltaU = 1.0 / rayDirectionPixel.x();
00444 m_tMaxU = m_tStart + (((m_initialU + 1) - entryPoint.x())
00445 / rayDirectionPixel.x());
00446 } else if(rayDirectionPixel.x() < 0.0) {
00447 m_stepU = -1;
00448 m_tDeltaU = -(1.0 / rayDirectionPixel.x());
00449 m_tMaxU = m_tStart + ((m_initialU - entryPoint.x())
00450 / rayDirectionPixel.x());
00451 } else {
00452 m_stepU = 0;
00453 m_tDeltaU = std::numeric_limits<double>::max();
00454 m_tMaxU = std::numeric_limits<double>::max();
00455 }
00456 if(rayDirectionPixel.y() > 0.0) {
00457 m_stepV = 1;
00458 m_tDeltaV = 1.0 / rayDirectionPixel.y();
00459 m_tMaxV = m_tStart + (((m_initialV + 1) - entryPoint.y())
00460 / rayDirectionPixel.y());
00461 } else if(rayDirectionPixel.y() < 0.0) {
00462 m_stepV = -1;
00463 m_tDeltaV = -(1.0 / rayDirectionPixel.y());
00464 m_tMaxV = m_tStart + ((m_initialV - entryPoint.y())
00465 / rayDirectionPixel.y());
00466 } else {
00467 m_stepV = 0;
00468 m_tDeltaV = std::numeric_limits<double>::max();
00469 m_tMaxV = std::numeric_limits<double>::max();
00470 }
00471 }
00472
00473
00474
00475 template <class ARRAY2D>
00476 AmanatidesWoo2D<ARRAY2D>::
00477 AmanatidesWoo2D(const AmanatidesWoo2D& source)
00478 : m_data(source.m_data),
00479 m_initialU(source.m_initialU),
00480 m_initialV(source.m_initialV),
00481 m_stepU(source.m_stepU),
00482 m_stepV(source.m_stepV),
00483 m_tDeltaU(source.m_tDeltaU),
00484 m_tDeltaV(source.m_tDeltaV),
00485 m_tMaxU(source.m_tMaxU),
00486 m_tMaxV(source.m_tMaxV),
00487 m_tStart(source.m_tStart),
00488 m_validIntersection(source.m_validIntersection)
00489 {
00490
00491 }
00492
00493 template <class ARRAY2D>
00494 AmanatidesWoo2D<ARRAY2D>::
00495 ~AmanatidesWoo2D() {};
00496
00497 template <class ARRAY2D>
00498 typename AmanatidesWoo2D<ARRAY2D>::iterator
00499 AmanatidesWoo2D<ARRAY2D>::
00500 begin()
00501 {
00502 return AmanatidesWoo2DIterator<ARRAY2D>(
00503 m_data, m_initialU, m_initialV, m_stepU, m_stepV, m_tMaxU, m_tMaxV,
00504 m_tDeltaU, m_tDeltaV, m_tStart);
00505 }
00506
00507 template <class ARRAY2D>
00508 typename AmanatidesWoo2D<ARRAY2D>::iterator
00509 AmanatidesWoo2D<ARRAY2D>::
00510 end()
00511 {
00512
00513
00514
00515
00516 return AmanatidesWoo2DIterator<ARRAY2D>(
00517 m_data, -1, -1, m_stepU, m_stepV, m_tMaxU, m_tMaxV,
00518 m_tDeltaU, m_tDeltaV, m_tStart);
00519 }
00520
00521 template <class ARRAY2D>
00522 inline bool
00523 AmanatidesWoo2D<ARRAY2D>::
00524 validIntersection()
00525 {
00526 return m_validIntersection;
00527 }
00528
00529 template <class ARRAY2D>
00530 AmanatidesWoo2D<ARRAY2D>&
00531 AmanatidesWoo2D<ARRAY2D>::
00532 operator=(const AmanatidesWoo2D& source)
00533 {
00534 m_data = source.m_data;
00535 m_initialU = source.m_initialU;
00536 m_initialV = source.m_initialV;
00537 m_stepU = source.m_stepU;
00538 m_stepV = source.m_stepV;
00539 m_tDeltaU = source.m_tDeltaU;
00540 m_tDeltaV = source.m_tDeltaV;
00541 m_tMaxU = source.m_tMaxU;
00542 m_tMaxV = source.m_tMaxV;
00543 m_tStart = source.m_tStart;
00544 m_validIntersection = source.m_validIntersection;
00545 return *this;
00546 }
00547
00548 template <class ARRAY2D>
00549 std::pair<double, double>
00550 AmanatidesWoo2D<ARRAY2D>::
00551 findEntryAndExitPoints(const Vector2D& rayOriginPixel,
00552 const Vector2D& rayDirectionPixel,
00553 const ARRAY2D& data)
00554 {
00555
00556
00557
00558
00559
00560 double tIntersectU0 = findIntersection(
00561 rayOriginPixel, rayDirectionPixel, Vector2D(1.0, 0.0), 0.0,
00562 std::numeric_limits<double>::min());
00563
00564
00565
00566
00567 double tIntersectU1 = findIntersection(
00568 rayOriginPixel, rayDirectionPixel, Vector2D(1.0, 0.0), data.columns(),
00569 std::numeric_limits<double>::max());
00570
00571
00572
00573
00574 double tIntersectV0 = findIntersection(
00575 rayOriginPixel, rayDirectionPixel, Vector2D(0.0, 1.0), 0.0,
00576 std::numeric_limits<double>::min());
00577
00578
00579
00580
00581 double tIntersectV1 = findIntersection(
00582 rayOriginPixel, rayDirectionPixel, Vector2D(0.0, 1.0), data.rows(),
00583 std::numeric_limits<double>::max());
00584
00585
00586 double tMinU = std::min(tIntersectU0, tIntersectU1);
00587 double tMinV = std::min(tIntersectV0, tIntersectV1);
00588 double tMaxU = std::max(tIntersectU0, tIntersectU1);
00589 double tMaxV = std::max(tIntersectV0, tIntersectV1);
00590
00591
00592 double tEntry = std::max(tMinU, tMinV);
00593
00594 double tExit = std::min(tMaxU, tMaxV);
00595
00596
00597 return std::make_pair(tEntry, tExit);
00598 }
00599
00600 template <class ARRAY2D>
00601 double
00602 AmanatidesWoo2D<ARRAY2D>::
00603 findIntersection(const Vector2D& rayOrigin,
00604 const Vector2D& rayDirection,
00605 const Vector2D& bVector,
00606 double cConstant,
00607 double defaultValue)
00608 {
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621 double denominator = dot(rayDirection, bVector);
00622 if(denominator == 0.0) {
00623 return defaultValue;
00624 }
00625
00626 return (cConstant - dot(rayOrigin, bVector)) / denominator;
00627 }
00628
00629 }
00630
00631 }
00632
00633 #endif // #ifndef _DLR_NUMERIC_AMANATIDESWOO2D_H_