00001
00015 #ifndef _DLR_NUMERIC_AMANATIDESWOO3D_H_
00016 #define _DLR_NUMERIC_AMANATIDESWOO3D_H_
00017
00018 #include <iostream>
00019 #include <limits>
00020 #include <dlrCommon/exception.h>
00021 #include <dlrNumeric/vector3D.h>
00022 #include <dlrNumeric/transform3D.h>
00023 #include <dlrNumeric/amanatidesWoo3DIterator.h>
00024
00025 namespace dlr {
00026
00027 namespace numeric {
00028
00083 template <class ARRAY3D>
00084 class AmanatidesWoo3D {
00085 public:
00086
00087
00095 typedef AmanatidesWoo3DIterator<ARRAY3D> iterator;
00096
00097
00098
00099
00100
00101
00102
00137 AmanatidesWoo3D(ARRAY3D& data,
00138 const Transform3D& voxelTworld,
00139 const Vector3D& rayOrigin,
00140 const Vector3D& rayDirection,
00141 bool downstreamOnly=true);
00142
00143
00151 AmanatidesWoo3D(const AmanatidesWoo3D& source);
00152
00157 ~AmanatidesWoo3D();
00158
00177 iterator
00178 begin();
00179
00190 iterator
00191 end();
00192
00199 ARRAY3D&
00200 getData() {return m_data;}
00201
00216 inline bool
00217 validIntersection();
00218
00227 AmanatidesWoo3D&
00228 operator=(const AmanatidesWoo3D& source);
00229
00230 private:
00231
00248 std::pair<double, double>
00249 findEntryAndExitPoints(const Vector3D& rayOriginVoxel,
00250 const Vector3D& rayDirectionVoxel,
00251 const ARRAY3D& m_data);
00252
00264 double
00265 findIntersection(const Vector3D& rayOrigin,
00266 const Vector3D& rayDirection,
00267 const Vector3D& bVector,
00268 double cConstant,
00269 double defaultValue);
00270
00273 ARRAY3D& m_data;
00274
00277 int m_initialU;
00278
00281 int m_initialV;
00282
00285 int m_initialW;
00286
00290 int m_stepU;
00291
00295 int m_stepV;
00296
00300 int m_stepW;
00301
00304 double m_tDeltaU;
00305
00308 double m_tDeltaV;
00309
00312 double m_tDeltaW;
00313
00317 double m_tMaxU;
00318
00322 double m_tMaxV;
00323
00327 double m_tMaxW;
00328
00335 double m_tStart;
00336
00339 bool m_validIntersection;
00340 };
00341
00342 }
00343
00344 }
00345
00346
00347
00348
00349 namespace dlr {
00350
00351 using numeric::AmanatidesWoo3D;
00352
00353 }
00354
00355
00356
00357
00358
00359
00360 namespace dlr {
00361
00362 namespace numeric {
00363
00364 template <class ARRAY3D>
00365 AmanatidesWoo3D<ARRAY3D>::
00366 AmanatidesWoo3D(ARRAY3D& data,
00367 const Transform3D& voxelTworld,
00368 const Vector3D& rayOrigin,
00369 const Vector3D& rayDirection,
00370 bool downstreamOnly)
00371 : m_data(data),
00372 m_initialU(-1),
00373 m_initialV(-1),
00374 m_initialW(-1),
00375
00376 m_stepU(),
00377 m_stepV(),
00378 m_stepW(),
00379 m_tDeltaU(),
00380 m_tDeltaV(),
00381 m_tDeltaW(),
00382 m_tMaxU(),
00383 m_tMaxV(),
00384 m_tMaxW(),
00385 m_tStart(),
00386 m_validIntersection(true)
00387 {
00388
00389 Vector3D rayOriginVoxel = voxelTworld * rayOrigin;
00390 Vector3D rayDirectionVoxel =
00391 (voxelTworld * (rayOrigin + rayDirection)) - rayOriginVoxel;
00392
00393
00394
00395
00396
00397
00398 std::pair<double, double> tEntry_tExit =
00399 this->findEntryAndExitPoints(rayOriginVoxel, rayDirectionVoxel, m_data);
00400
00401
00402
00403
00404
00405 if(downstreamOnly && (tEntry_tExit.first < 0.0)) {
00406 tEntry_tExit.first = 0.0;
00407 }
00408
00409
00410
00411
00412 if(tEntry_tExit.second <= tEntry_tExit.first) {
00413 m_validIntersection = false;
00414 return;
00415 }
00416
00417
00418 Vector3D entryPoint =
00419 rayOriginVoxel + tEntry_tExit.first * rayDirectionVoxel;
00420
00421
00422
00423 if(entryPoint.x() < 0.0) {
00424 entryPoint.x() = 0.0;
00425 }
00426 if(entryPoint.y() < 0.0) {
00427 entryPoint.y() = 0.0;
00428 }
00429 if(entryPoint.z() < 0.0) {
00430 entryPoint.z() = 0.0;
00431 }
00432
00433
00434
00435
00436
00437
00438 m_initialU = static_cast<int>(entryPoint.x());
00439 m_initialV = static_cast<int>(entryPoint.y());
00440 m_initialW = static_cast<int>(entryPoint.z());
00441
00442
00443
00444
00445
00446
00447
00448 if(m_initialU == static_cast<int>(m_data.shape()[2])) {
00449 --m_initialU;
00450 }
00451 if(m_initialV == static_cast<int>(m_data.shape()[1])) {
00452 --m_initialV;
00453 }
00454 if(m_initialW == static_cast<int>(m_data.shape()[0])) {
00455 --m_initialW;
00456 }
00457
00458
00459 if((m_initialU >= static_cast<int>(m_data.shape()[2]))
00460 || (m_initialV >= static_cast<int>(m_data.shape()[1]))
00461 || (m_initialW >= static_cast<int>(m_data.shape()[0]))) {
00462 DLR_THROW3(LogicException,
00463 "AmanatidesWoo3D::AmanatidesWoo3D(ARRAY3D&, ...)",
00464 "Illegal value for m_initialU, m_initialV, or m_initialW.");
00465 }
00466
00467
00468 m_tStart = tEntry_tExit.first;
00469
00470
00471
00472
00473
00474 if(rayDirectionVoxel.x() > 0.0) {
00475 m_stepU = 1;
00476 m_tDeltaU = 1.0 / rayDirectionVoxel.x();
00477 m_tMaxU = m_tStart + (((m_initialU + 1) - entryPoint.x())
00478 / rayDirectionVoxel.x());
00479 } else if(rayDirectionVoxel.x() < 0.0) {
00480 m_stepU = -1;
00481 m_tDeltaU = -(1.0 / rayDirectionVoxel.x());
00482 m_tMaxU = m_tStart + ((m_initialU - entryPoint.x())
00483 / rayDirectionVoxel.x());
00484 } else {
00485 m_stepU = 0;
00486 m_tDeltaU = std::numeric_limits<double>::max();
00487 m_tMaxU = std::numeric_limits<double>::max();
00488 }
00489 if(rayDirectionVoxel.y() > 0.0) {
00490 m_stepV = 1;
00491 m_tDeltaV = 1.0 / rayDirectionVoxel.y();
00492 m_tMaxV = m_tStart + (((m_initialV + 1) - entryPoint.y())
00493 / rayDirectionVoxel.y());
00494 } else if(rayDirectionVoxel.y() < 0.0) {
00495 m_stepV = -1;
00496 m_tDeltaV = -(1.0 / rayDirectionVoxel.y());
00497 m_tMaxV = m_tStart + ((m_initialV - entryPoint.y())
00498 / rayDirectionVoxel.y());
00499 } else {
00500 m_stepV = 0;
00501 m_tDeltaV = std::numeric_limits<double>::max();
00502 m_tMaxV = std::numeric_limits<double>::max();
00503 }
00504 if(rayDirectionVoxel.z() > 0.0) {
00505 m_stepW = 1;
00506 m_tDeltaW = 1.0 / rayDirectionVoxel.z();
00507 m_tMaxW = m_tStart + (((m_initialW + 1) - entryPoint.z())
00508 / rayDirectionVoxel.z());
00509 } else if(rayDirectionVoxel.z() < 0.0) {
00510 m_stepW = -1;
00511 m_tDeltaW = -(1.0 / rayDirectionVoxel.z());
00512 m_tMaxW = m_tStart + ((m_initialW - entryPoint.z())
00513 / rayDirectionVoxel.z());
00514 } else {
00515 m_stepW = 0;
00516 m_tDeltaW = std::numeric_limits<double>::max();
00517 m_tMaxW = std::numeric_limits<double>::max();
00518 }
00519 }
00520
00521 template <class ARRAY3D>
00522 AmanatidesWoo3D<ARRAY3D>::
00523 AmanatidesWoo3D(const AmanatidesWoo3D& source)
00524 : m_data(source.m_data),
00525 m_initialU(source.m_initialU),
00526 m_initialV(source.m_initialV),
00527 m_initialW(source.m_initialW),
00528 m_stepU(source.m_stepU),
00529 m_stepV(source.m_stepV),
00530 m_stepW(source.m_stepW),
00531 m_tDeltaU(source.m_tDeltaU),
00532 m_tDeltaV(source.m_tDeltaV),
00533 m_tDeltaW(source.m_tDeltaW),
00534 m_tMaxU(source.m_tMaxU),
00535 m_tMaxV(source.m_tMaxV),
00536 m_tMaxW(source.m_tMaxW),
00537 m_tStart(source.m_tStart),
00538 m_validIntersection(source.m_validIntersection)
00539 {
00540
00541 }
00542
00543 template <class ARRAY3D>
00544 AmanatidesWoo3D<ARRAY3D>::
00545 ~AmanatidesWoo3D() {};
00546
00547 template <class ARRAY3D>
00548 typename AmanatidesWoo3D<ARRAY3D>::iterator
00549 AmanatidesWoo3D<ARRAY3D>::
00550 begin()
00551 {
00552 return AmanatidesWoo3DIterator<ARRAY3D>(
00553 m_data, m_initialU, m_initialV, m_initialW, m_stepU, m_stepV, m_stepW,
00554 m_tMaxU, m_tMaxV, m_tMaxW, m_tDeltaU, m_tDeltaV, m_tDeltaW, m_tStart);
00555 }
00556
00557 template <class ARRAY3D>
00558 typename AmanatidesWoo3D<ARRAY3D>::iterator
00559 AmanatidesWoo3D<ARRAY3D>::
00560 end()
00561 {
00562
00563
00564
00565
00566 return AmanatidesWoo3DIterator<ARRAY3D>(
00567 m_data, -1, -1, -1, m_stepU, m_stepV, m_stepW,
00568 m_tMaxU, m_tMaxV, m_tMaxW, m_tDeltaU, m_tDeltaV, m_tDeltaW, m_tStart);
00569 }
00570
00571 template <class ARRAY3D>
00572 inline bool
00573 AmanatidesWoo3D<ARRAY3D>::
00574 validIntersection()
00575 {
00576 return m_validIntersection;
00577 }
00578
00579 template <class ARRAY3D>
00580 AmanatidesWoo3D<ARRAY3D>&
00581 AmanatidesWoo3D<ARRAY3D>::
00582 operator=(const AmanatidesWoo3D& source)
00583 {
00584 m_data = source.m_data;
00585 m_initialU = source.m_initialU;
00586 m_initialV = source.m_initialV;
00587 m_initialW = source.m_initialW;
00588 m_stepU = source.m_stepU;
00589 m_stepV = source.m_stepV;
00590 m_stepW = source.m_stepW;
00591 m_tDeltaU = source.m_tDeltaU;
00592 m_tDeltaV = source.m_tDeltaV;
00593 m_tDeltaW = source.m_tDeltaW;
00594 m_tMaxU = source.m_tMaxU;
00595 m_tMaxV = source.m_tMaxV;
00596 m_tMaxW = source.m_tMaxW;
00597 m_tStart = source.m_tStart;
00598 m_validIntersection = source.m_validIntersection;
00599 return *this;
00600 }
00601
00602 template <class ARRAY3D>
00603 std::pair<double, double>
00604 AmanatidesWoo3D<ARRAY3D>::
00605 findEntryAndExitPoints(const Vector3D& rayOriginVoxel,
00606 const Vector3D& rayDirectionVoxel,
00607 const ARRAY3D& m_data)
00608 {
00609
00610
00611
00612
00613 double tIntersectU0 = findIntersection(
00614 rayOriginVoxel, rayDirectionVoxel, Vector3D(1.0, 0.0, 0.0),
00615 0.0, std::numeric_limits<double>::min());
00616
00617
00618
00619
00620 double tIntersectU1 = findIntersection(
00621 rayOriginVoxel, rayDirectionVoxel, Vector3D(1.0, 0.0, 0.0),
00622 m_data.shape()[2], std::numeric_limits<double>::max());
00623
00624
00625
00626 double tIntersectV0 = findIntersection(
00627 rayOriginVoxel, rayDirectionVoxel, Vector3D(0.0, 1.0, 0.0),
00628 0.0, std::numeric_limits<double>::min());
00629
00630
00631
00632
00633 double tIntersectV1 = findIntersection(
00634 rayOriginVoxel, rayDirectionVoxel, Vector3D(0.0, 1.0, 0.0),
00635 m_data.shape()[1], std::numeric_limits<double>::max());
00636
00637
00638
00639 double tIntersectW0 = findIntersection(
00640 rayOriginVoxel, rayDirectionVoxel, Vector3D(0.0, 0.0, 1.0),
00641 0.0, std::numeric_limits<double>::min());
00642
00643
00644
00645
00646 double tIntersectW1 = findIntersection(
00647 rayOriginVoxel, rayDirectionVoxel, Vector3D(0.0, 0.0, 1.0),
00648 m_data.shape()[0], std::numeric_limits<double>::max());
00649
00650
00651 double tMinU = std::min(tIntersectU0, tIntersectU1);
00652 double tMinV = std::min(tIntersectV0, tIntersectV1);
00653 double tMinW = std::min(tIntersectW0, tIntersectW1);
00654 double tMaxU = std::max(tIntersectU0, tIntersectU1);
00655 double tMaxV = std::max(tIntersectV0, tIntersectV1);
00656 double tMaxW = std::max(tIntersectW0, tIntersectW1);
00657
00658
00659 double tEntry = std::max(tMinU, std::max(tMinV, tMinW));
00660
00661 double tExit = std::min(tMaxU, std::min(tMaxV, tMaxW));
00662
00663
00664 return std::make_pair(tEntry, tExit);
00665 }
00666
00667 template <class ARRAY3D>
00668 double
00669 AmanatidesWoo3D<ARRAY3D>::
00670 findIntersection(const Vector3D& rayOrigin,
00671 const Vector3D& rayDirection,
00672 const Vector3D& bVector,
00673 double cConstant,
00674 double defaultValue)
00675 {
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688 double denominator = dot(rayDirection, bVector);
00689 if(denominator == 0.0) {
00690 return defaultValue;
00691 }
00692
00693 return (cConstant - dot(rayOrigin, bVector)) / denominator;
00694 }
00695
00696 }
00697
00698 }
00699
00700 #endif // #ifndef _DLR_NUMERIC_AMANATIDESWOO3D_H_