[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
vigra/multi_iterator_coupled.hxx | ![]() |
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 2011-2012 by Stefan Schmidt and Ullrich Koethe */ 00004 /* */ 00005 /* This file is part of the VIGRA computer vision library. */ 00006 /* The VIGRA Website is */ 00007 /* http://hci.iwr.uni-heidelberg.de/vigra/ */ 00008 /* Please direct questions, bug reports, and contributions to */ 00009 /* ullrich.koethe@iwr.uni-heidelberg.de or */ 00010 /* vigra@informatik.uni-hamburg.de */ 00011 /* */ 00012 /* Permission is hereby granted, free of charge, to any person */ 00013 /* obtaining a copy of this software and associated documentation */ 00014 /* files (the "Software"), to deal in the Software without */ 00015 /* restriction, including without limitation the rights to use, */ 00016 /* copy, modify, merge, publish, distribute, sublicense, and/or */ 00017 /* sell copies of the Software, and to permit persons to whom the */ 00018 /* Software is furnished to do so, subject to the following */ 00019 /* conditions: */ 00020 /* */ 00021 /* The above copyright notice and this permission notice shall be */ 00022 /* included in all copies or substantial portions of the */ 00023 /* Software. */ 00024 /* */ 00025 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ 00026 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ 00027 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ 00028 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ 00029 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ 00030 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ 00031 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ 00032 /* OTHER DEALINGS IN THE SOFTWARE. */ 00033 /* */ 00034 /************************************************************************/ 00035 00036 #ifndef MULTI_ITERATOR_COUPLED_HXX_ 00037 #define MULTI_ITERATOR_COUPLED_HXX_ 00038 00039 #include "metaprogramming.hxx" 00040 #include "multi_iterator.hxx" 00041 00042 namespace vigra { 00043 00044 /** \addtogroup MultiIteratorGroup 00045 */ 00046 //@{ 00047 00048 00049 // FIXME: this should go into its separate header file, 00050 // together with the calculation of neighborhod offsets for GridGraph 00051 template <unsigned int N, unsigned int DIMENSION=N-1> 00052 struct NeighborhoodTypeImpl 00053 { 00054 typedef typename MultiArrayShape<N>::type shape_type; 00055 00056 static unsigned int exec(shape_type const & point, shape_type const & shape) 00057 { 00058 unsigned int res = NeighborhoodTypeImpl<N, DIMENSION-1>::exec(point, shape); 00059 if(point[DIMENSION] == 0) 00060 res |= (1 << 2*DIMENSION); 00061 if(point[DIMENSION] == shape[DIMENSION]-1) 00062 res |= (2 << 2*DIMENSION); 00063 return res; 00064 } 00065 }; 00066 00067 template <unsigned int N> 00068 struct NeighborhoodTypeImpl<N, 0> 00069 { 00070 typedef typename MultiArrayShape<N>::type shape_type; 00071 static const unsigned int DIMENSION = 0; 00072 00073 static unsigned int exec(shape_type const & point, shape_type const & shape) 00074 { 00075 unsigned int res = 0; 00076 if(point[DIMENSION] == 0) 00077 res |= (1 << 2*DIMENSION); 00078 if(point[DIMENSION] == shape[DIMENSION]-1) 00079 res |= (2 << 2*DIMENSION); 00080 return res; 00081 } 00082 }; 00083 00084 /** 00085 Handle class, used by CoupledScanOrderIterator as the value type to simultaneously itearate over multiple images. 00086 */ 00087 template <class T, class NEXT> 00088 class CoupledHandle 00089 : public NEXT 00090 { 00091 public: 00092 typedef NEXT base_type; 00093 typedef CoupledHandle<T, NEXT> self_type; 00094 00095 static const int index = NEXT::index + 1; // index of this member of the chain 00096 static const unsigned int dimensions = NEXT::dimensions; 00097 00098 typedef T value_type; 00099 typedef T * pointer; 00100 typedef T const * const_pointer; 00101 typedef T & reference; 00102 typedef T const & const_reference; 00103 typedef typename base_type::shape_type shape_type; 00104 00105 CoupledHandle() 00106 : base_type(), 00107 pointer_(), 00108 strides_() 00109 {} 00110 00111 CoupledHandle(const_pointer p, shape_type const & strides, NEXT const & next) 00112 : base_type(next), 00113 pointer_(const_cast<pointer>(p)), 00114 strides_(strides) 00115 {} 00116 00117 template <class Stride> 00118 CoupledHandle(MultiArrayView<dimensions, T, Stride> const & v, NEXT const & next) 00119 : base_type(next), 00120 pointer_(const_cast<pointer>(v.data())), 00121 strides_(v.stride()) 00122 { 00123 vigra_precondition(v.shape() == this->shape(), "createCoupledIterator(): shape mismatch."); 00124 } 00125 00126 template<int DIMENSION> 00127 inline void increment() 00128 { 00129 pointer_ += strides_[DIMENSION]; 00130 base_type::template increment<DIMENSION>(); 00131 } 00132 00133 template<int DIMENSION> 00134 inline void decrement() 00135 { 00136 pointer_ -= strides_[DIMENSION]; 00137 base_type::template decrement<DIMENSION>(); 00138 } 00139 00140 // TODO: test if making the above a default case of the this hurts performance 00141 template<int DIMENSION> 00142 inline void increment(MultiArrayIndex offset) 00143 { 00144 pointer_ += offset*strides_[DIMENSION]; 00145 base_type::template increment<DIMENSION>(offset); 00146 } 00147 00148 template<int DIMENSION> 00149 inline void decrement(MultiArrayIndex offset) 00150 { 00151 pointer_ -= offset*strides_[DIMENSION]; 00152 base_type::template decrement<DIMENSION>(offset); 00153 } 00154 00155 void restrictToSubarray(shape_type const & start, shape_type const & end) 00156 { 00157 pointer_ += dot(start, strides_); 00158 base_type::restrictToSubarray(start, end); 00159 } 00160 00161 // ptr access 00162 reference operator*() 00163 { 00164 return *pointer_; 00165 } 00166 00167 const_reference operator*() const 00168 { 00169 return *pointer_; 00170 } 00171 00172 pointer operator->() 00173 { 00174 return pointer_; 00175 } 00176 00177 const_pointer operator->() const 00178 { 00179 return pointer_; 00180 } 00181 00182 pointer ptr() 00183 { 00184 return pointer_; 00185 } 00186 00187 const_pointer ptr() const 00188 { 00189 return pointer_; 00190 } 00191 00192 shape_type const & strides() const 00193 { 00194 return strides_; 00195 } 00196 00197 pointer pointer_; 00198 shape_type strides_; 00199 }; 00200 00201 00202 template <int N> 00203 class CoupledHandle<TinyVector<MultiArrayIndex, N>, void> 00204 { 00205 public: 00206 static const int index = 0; // index of this member of the chain 00207 static const unsigned int dimensions = N; 00208 00209 typedef typename MultiArrayShape<N>::type value_type; 00210 typedef value_type const * pointer; 00211 typedef value_type const * const_pointer; 00212 typedef value_type const & reference; 00213 typedef value_type const & const_reference; 00214 typedef value_type shape_type; 00215 typedef CoupledHandle<value_type, void> self_type; 00216 00217 CoupledHandle() 00218 : point_(), 00219 shape_(), 00220 scanOrderIndex_() 00221 {} 00222 00223 CoupledHandle(value_type const & shape) 00224 : point_(), 00225 shape_(shape), 00226 scanOrderIndex_() 00227 {} 00228 00229 CoupledHandle(typename MultiArrayShape<N+1>::type const & shape) 00230 : point_(), 00231 shape_(shape.begin()), 00232 scanOrderIndex_() 00233 {} 00234 00235 template<int DIMENSION> 00236 inline void increment() 00237 { 00238 ++point_[DIMENSION]; 00239 } 00240 00241 template<int DIMENSION> 00242 inline void decrement() 00243 { 00244 --point_[DIMENSION]; 00245 } 00246 00247 // TODO: test if making the above a default case of the this hurts performance 00248 template<int DIMENSION> 00249 inline void increment(MultiArrayIndex offset) 00250 { 00251 point_[DIMENSION] += offset; 00252 } 00253 00254 template<int DIMENSION> 00255 inline void decrement(MultiArrayIndex offset) 00256 { 00257 point_[DIMENSION] -= offset; 00258 } 00259 00260 void restrictToSubarray(shape_type const & start, shape_type const & end) 00261 { 00262 point_ = shape_type(); 00263 shape_ = end - start; 00264 scanOrderIndex_ = 0; 00265 } 00266 00267 inline void incrementIndex() 00268 { 00269 ++scanOrderIndex_; 00270 } 00271 00272 inline void decrementIndex() 00273 { 00274 --scanOrderIndex_; 00275 } 00276 00277 inline void incrementIndex(MultiArrayIndex offset) 00278 { 00279 scanOrderIndex_ += offset; 00280 } 00281 00282 inline void decrementIndex(MultiArrayIndex offset) 00283 { 00284 scanOrderIndex_ -= offset; 00285 } 00286 00287 // access 00288 MultiArrayIndex scanOrderIndex() const 00289 { 00290 return scanOrderIndex_; 00291 } 00292 00293 // access 00294 const_reference point() const 00295 { 00296 return point_; 00297 } 00298 00299 // access 00300 const_reference shape() const 00301 { 00302 return shape_; 00303 } 00304 00305 const_reference operator*() const 00306 { 00307 return point_; 00308 } 00309 00310 const_pointer operator->() const 00311 { 00312 return &point_; 00313 } 00314 00315 const_pointer ptr() const 00316 { 00317 return &point_; 00318 } 00319 00320 unsigned int neighborhoodType() const 00321 { 00322 return NeighborhoodTypeImpl<N>::exec(point_, shape_); 00323 } 00324 00325 value_type point_, shape_; 00326 MultiArrayIndex scanOrderIndex_; 00327 }; 00328 00329 template <class T> 00330 struct Multiband; 00331 00332 template <unsigned int N, class T, class StrideTag> 00333 class MultiArrayView<N, Multiband<T>, StrideTag> 00334 : public MultiArrayView<N, T, StrideTag> 00335 { 00336 public: 00337 MultiArrayView(MultiArrayView<N, T, StrideTag> const & v) 00338 : MultiArrayView<N, T, StrideTag>(v) 00339 {} 00340 }; 00341 00342 template <class T, class NEXT> 00343 class CoupledHandle<Multiband<T>, NEXT> 00344 : public NEXT 00345 { 00346 public: 00347 typedef NEXT base_type; 00348 typedef CoupledHandle<Multiband<T>, NEXT> self_type; 00349 00350 static const int index = NEXT::index + 1; // index of this member of the chain 00351 static const unsigned int dimensions = NEXT::dimensions; 00352 00353 typedef MultiArrayView<1, T, StridedArrayTag> value_type; 00354 typedef value_type * pointer; 00355 typedef value_type const * const_pointer; 00356 typedef value_type & reference; 00357 typedef value_type const & const_reference; 00358 typedef typename base_type::shape_type shape_type; 00359 00360 CoupledHandle() 00361 : base_type(), 00362 view_(), 00363 strides_() 00364 {} 00365 00366 CoupledHandle(const_reference p, shape_type const & strides, NEXT const & next) 00367 : base_type(next), 00368 view_(p), 00369 strides_(strides) 00370 {} 00371 00372 template <class Stride> 00373 CoupledHandle(MultiArrayView<dimensions+1, Multiband<T>, Stride> const & v, NEXT const & next) 00374 : base_type(next), 00375 view_(v.bindInner(shape_type())), 00376 strides_(v.bindOuter(0).stride()) 00377 { 00378 vigra_precondition(v.bindOuter(0).shape() == this->shape(), "createCoupledIterator(): shape mismatch."); 00379 } 00380 00381 template<int DIMENSION> 00382 inline void increment() 00383 { 00384 view_.unsafePtr() += strides_[DIMENSION]; 00385 base_type::template increment<DIMENSION>(); 00386 } 00387 00388 template<int DIMENSION> 00389 inline void decrement() 00390 { 00391 view_.unsafePtr() -= strides_[DIMENSION]; 00392 base_type::template decrement<DIMENSION>(); 00393 } 00394 00395 // TODO: test if making the above a default case of the this hurts performance 00396 template<int DIMENSION> 00397 inline void increment(MultiArrayIndex offset) 00398 { 00399 view_.unsafePtr() += offset*strides_[DIMENSION]; 00400 base_type::template increment<DIMENSION>(offset); 00401 } 00402 00403 template<int DIMENSION> 00404 inline void decrement(MultiArrayIndex offset) 00405 { 00406 view_.unsafePtr() -= offset*strides_[DIMENSION]; 00407 base_type::template decrement<DIMENSION>(offset); 00408 } 00409 00410 void restrictToSubarray(shape_type const & start, shape_type const & end) 00411 { 00412 view_.unsafePtr() += dot(start, strides_); 00413 base_type::restrictToSubarray(start, end); 00414 } 00415 00416 // ptr access 00417 reference operator*() 00418 { 00419 return view_; 00420 } 00421 00422 const_reference operator*() const 00423 { 00424 return view_; 00425 } 00426 00427 pointer operator->() 00428 { 00429 return &view_; 00430 } 00431 00432 const_pointer operator->() const 00433 { 00434 return &view_; 00435 } 00436 00437 pointer ptr() 00438 { 00439 return &view_; 00440 } 00441 00442 const_pointer ptr() const 00443 { 00444 return &view_; 00445 } 00446 00447 shape_type const & strides() const 00448 { 00449 return strides_; 00450 } 00451 00452 value_type view_; 00453 shape_type strides_; 00454 }; 00455 00456 template <unsigned TARGET_INDEX> 00457 struct Error__CoupledHandle_index_out_of_range; 00458 00459 namespace detail { 00460 00461 template <unsigned TARGET_INDEX, class Handle, bool isValid, unsigned int INDEX=Handle::index> 00462 struct CoupledHandleCastImpl 00463 { 00464 typedef typename CoupledHandleCastImpl<TARGET_INDEX, typename Handle::base_type, isValid>::type type; 00465 }; 00466 00467 template <unsigned TARGET_INDEX, class Handle, unsigned int INDEX> 00468 struct CoupledHandleCastImpl<TARGET_INDEX, Handle, false, INDEX> 00469 { 00470 typedef Error__CoupledHandle_index_out_of_range<TARGET_INDEX> type; 00471 }; 00472 00473 template <unsigned TARGET_INDEX, class Handle> 00474 struct CoupledHandleCastImpl<TARGET_INDEX, Handle, true, TARGET_INDEX> 00475 { 00476 typedef Handle type; 00477 }; 00478 00479 } // namespace detail 00480 00481 template <unsigned TARGET_INDEX, class Handle, unsigned int INDEX=Handle::index> 00482 struct CoupledHandleCast 00483 : public detail::CoupledHandleCastImpl<TARGET_INDEX, Handle, (TARGET_INDEX <= INDEX), INDEX> 00484 {}; 00485 00486 template <unsigned int TARGET_INDEX, class Handle> 00487 typename CoupledHandleCast<TARGET_INDEX, Handle>::type & 00488 cast(Handle & handle) 00489 { 00490 return handle; 00491 }; 00492 00493 template <unsigned int TARGET_INDEX, class Handle> 00494 typename CoupledHandleCast<TARGET_INDEX, Handle>::type const & 00495 cast(Handle const & handle) 00496 { 00497 return handle; 00498 }; 00499 00500 /** Returns reference to the element in the band of the handle with index TARGET_INDEX. 00501 */ 00502 template <unsigned int TARGET_INDEX, class Handle> 00503 typename CoupledHandleCast<TARGET_INDEX, Handle>::type::reference 00504 get(Handle & handle) 00505 { 00506 return *cast<TARGET_INDEX>(handle); 00507 }; 00508 00509 /** Returns a constant reference to the element in the band of the handle with index TARGET_INDEX. 00510 */ 00511 template <unsigned int TARGET_INDEX, class Handle> 00512 typename CoupledHandleCast<TARGET_INDEX, Handle>::type::const_reference 00513 get(Handle const & handle) 00514 { 00515 return *cast<TARGET_INDEX>(handle); 00516 }; 00517 00518 /********************************************************/ 00519 /* */ 00520 /* CoupledScanOrderIterator<N> */ 00521 /* */ 00522 /********************************************************/ 00523 00524 /** \brief Iterate over multiple images simultaneously in scan order. 00525 00526 The value type of this iterator is an instance of the handle class CoupledHandle. This allows to iterate over multiple arrays simultaneously. The coordinates can be accessed as a special band (index 0) in the handle. The scan-order is defined such that dimensions are iterated from front to back (first to last). 00527 00528 Instances of this class are usually constructed by calling createCoupledIterator() . 00529 00530 To get the type of a CoupledScanOrderIterator for arrays of a certain dimension and element types use CoupledIteratorType::type. 00531 00532 The iterator supports all functions listed in the STL documentation for 00533 <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random 00534 Access Iterators</a>. 00535 00536 Example of use: 00537 \code 00538 using namespace vigra; 00539 MultiArray<2, double> image1(Shape2(5, 5)); 00540 MultiArray<2, double> image2(Shape2(5, 5)); 00541 // fill image with data ... 00542 00543 typedef CoupledIteratorType<2, double, double>::type Iterator; // the type of the CoupledScanOrderIterator 00544 00545 Iterator start = createCoupledIterator(image1, image2); // create coupled iterator for simultaneous iteration over image1, image2 and their coordinates 00546 Iterator end = start.getEndIterator(); 00547 00548 for (Iterator it = start; it < end; ++it) { 00549 std::cout << "coordinates: " << it.get<0>() << std::endl; 00550 std::cout << "image1: " << it.get<1>() << std::endl; 00551 std::cout << "image2: " << it.get<2>() << std::endl; 00552 } 00553 00554 //random access: 00555 Iterator::value_type handle = start[15]; 00556 std::cout << "image1: " << get<1>(handle) << std::endl; 00557 \endcode 00558 00559 <b>\#include</b> <vigra/multi_iterator_coupled.hxx> 00560 00561 Namespace: vigra 00562 */ 00563 00564 template <unsigned int N, 00565 class HANDLES, 00566 int DIMENSION = N-1> 00567 class CoupledScanOrderIterator 00568 #ifndef DOXYGEN // doxygen doesn't understand this inheritance 00569 : protected CoupledScanOrderIterator<N, HANDLES, DIMENSION-1> 00570 #endif 00571 { 00572 typedef CoupledScanOrderIterator<N, HANDLES, DIMENSION-1> base_type; 00573 static const int dimension = DIMENSION; 00574 00575 public: 00576 00577 typedef typename MultiArrayShape<dimension+1>::type shape_type; 00578 typedef MultiArrayIndex difference_type; 00579 typedef CoupledScanOrderIterator iterator; 00580 typedef std::random_access_iterator_tag iterator_category; 00581 00582 typedef typename base_type::value_type value_type; 00583 00584 #ifdef DOXYGEN 00585 /** The type of the CoupledHandle. 00586 */ 00587 typedef HANDLES value_type; 00588 #endif 00589 00590 typedef typename base_type::reference reference; 00591 typedef typename base_type::const_reference const_reference; // FIXME: do we need both? 00592 typedef typename base_type::pointer pointer; 00593 00594 CoupledScanOrderIterator(value_type const & handles = value_type()) 00595 : base_type(handles) 00596 {} 00597 00598 value_type operator[](MultiArrayIndex i) const 00599 { 00600 return *(CoupledScanOrderIterator(*this) += i); 00601 } 00602 00603 CoupledScanOrderIterator & operator++() 00604 { 00605 base_type::operator++(); 00606 if(this->point()[dimension-1] == this->shape()[dimension-1]) 00607 { 00608 base_type::reset(); 00609 this->handles_.template increment<dimension>(); 00610 } 00611 return *this; 00612 } 00613 00614 CoupledScanOrderIterator operator++(int) 00615 { 00616 CoupledScanOrderIterator res(*this); 00617 ++*this; 00618 return res; 00619 } 00620 00621 CoupledScanOrderIterator & operator+=(MultiArrayIndex i) 00622 { 00623 // FIXME: this looks very expensive 00624 shape_type coordOffset; 00625 detail::ScanOrderToCoordinate<N>::exec(i+scanOrderIndex(), this->shape(), coordOffset); 00626 coordOffset -= point(); 00627 moveRelative(coordOffset); 00628 this->handles_.scanOrderIndex_ += i; 00629 return *this; 00630 } 00631 00632 CoupledScanOrderIterator & operator+=(const shape_type &coordOffset) 00633 { 00634 moveRelative(coordOffset); 00635 this->handles_.scanOrderIndex_ += detail::CoordinateToScanOrder<N>::exec(this->shape(), coordOffset); 00636 return *this; 00637 } 00638 00639 CoupledScanOrderIterator & operator--() 00640 { 00641 base_type::operator--(); 00642 if(this->point()[dimension-1] == -1) 00643 { 00644 base_type::inverseReset(); 00645 this->handles_.template decrement<dimension>(); 00646 } 00647 return *this; 00648 } 00649 00650 CoupledScanOrderIterator operator--(int) 00651 { 00652 CoupledScanOrderIterator res(*this); 00653 --*this; 00654 return res; 00655 } 00656 00657 CoupledScanOrderIterator & operator-=(MultiArrayIndex i) 00658 { 00659 return operator+=(-i); 00660 } 00661 00662 CoupledScanOrderIterator & operator-=(const shape_type &coordOffset) 00663 { 00664 return operator+=(-coordOffset); 00665 } 00666 00667 /** Returns CoupledScanOrderIterator pointing beyond the last element. 00668 */ 00669 CoupledScanOrderIterator getEndIterator() const 00670 { 00671 return operator+(prod(this->shape())); 00672 } 00673 00674 CoupledScanOrderIterator operator+(MultiArrayIndex d) const 00675 { 00676 return CoupledScanOrderIterator(*this) += d; 00677 } 00678 00679 CoupledScanOrderIterator operator-(MultiArrayIndex d) const 00680 { 00681 return CoupledScanOrderIterator(*this) -= d; 00682 } 00683 00684 CoupledScanOrderIterator operator+(const shape_type &coordOffset) const 00685 { 00686 return CoupledScanOrderIterator(*this) += coordOffset; 00687 } 00688 00689 CoupledScanOrderIterator operator-(const shape_type &coordOffset) const 00690 { 00691 return CoupledScanOrderIterator(*this) -= coordOffset; 00692 } 00693 00694 MultiArrayIndex operator-(CoupledScanOrderIterator const & r) const 00695 { 00696 return base_type::operator-(r); 00697 } 00698 00699 bool operator==(CoupledScanOrderIterator const & r) 00700 { 00701 return base_type::operator==(r); 00702 } 00703 00704 bool operator!=(CoupledScanOrderIterator const & r) const 00705 { 00706 return base_type::operator!=(r); 00707 } 00708 00709 bool operator<(CoupledScanOrderIterator const & r) const 00710 { 00711 return base_type::operator<(r); 00712 } 00713 00714 bool operator<=(CoupledScanOrderIterator const & r) const 00715 { 00716 return base_type::operator<=(r); 00717 } 00718 00719 bool operator>(CoupledScanOrderIterator const & r) const 00720 { 00721 return base_type::operator>(r); 00722 } 00723 00724 bool operator>=(CoupledScanOrderIterator const & r) const 00725 { 00726 return base_type::operator>=(r); 00727 } 00728 00729 using base_type::operator*; 00730 using base_type::point; 00731 using base_type::shape; 00732 using base_type::scanOrderIndex; 00733 using base_type::atBorder; 00734 using base_type::neighborhoodType; 00735 using base_type::get; 00736 00737 #ifdef DOXYGEN 00738 00739 /** Returns reference to the element in the band with index TARGET_INDEX. 00740 */ 00741 template<unsigned int TARGET_INDEX> 00742 typename CoupledHandleCast<TARGET_INDEX, value_type>::type::reference 00743 get() 00744 { 00745 return vigra::get<TARGET_INDEX>(handles_); 00746 } 00747 00748 /** Returns constant reference to the element in the band with index TARGET_INDEX. 00749 */ 00750 template<unsigned int TARGET_INDEX> 00751 typename CoupledHandleCast<TARGET_INDEX, value_type>::type::const_reference 00752 get() const 00753 { 00754 return vigra::get<TARGET_INDEX>(handles_); 00755 } 00756 #endif 00757 00758 protected: 00759 void reset() 00760 { 00761 this->handles_.template decrement<dimension>(this->shape()[dimension]); 00762 } 00763 00764 void inverseReset() 00765 { 00766 this->handles_.template increment<dimension>(this->shape()[dimension]); 00767 } 00768 00769 void moveRelative(typename value_type::shape_type const & coordOffset) 00770 { 00771 base_type::moveRelative(coordOffset); 00772 this->handles_.template increment<dimension>(coordOffset[dimension]); 00773 } 00774 }; 00775 00776 00777 00778 template <unsigned int N, class HANDLES> 00779 class CoupledScanOrderIterator<N, HANDLES, 0> 00780 { 00781 static const int dimension = 0; 00782 00783 public: 00784 00785 typedef CoupledScanOrderIterator<N, HANDLES, 0> self_type; 00786 typedef HANDLES value_type; 00787 typedef MultiArrayIndex difference_type; 00788 typedef value_type & reference; 00789 typedef value_type const & const_reference; 00790 typedef value_type * pointer; 00791 typedef typename MultiArrayShape<1>::type shape_type; 00792 typedef CoupledScanOrderIterator iterator; 00793 typedef std::random_access_iterator_tag iterator_category; 00794 00795 CoupledScanOrderIterator(value_type const & handles = value_type()) 00796 : handles_(handles) 00797 {} 00798 00799 CoupledScanOrderIterator & operator++() 00800 { 00801 handles_.template increment<dimension>(); 00802 handles_.incrementIndex(); 00803 return *this; 00804 } 00805 00806 CoupledScanOrderIterator operator++(int) 00807 { 00808 CoupledScanOrderIterator res(*this); 00809 ++*this; 00810 return res; 00811 } 00812 00813 CoupledScanOrderIterator & operator+=(MultiArrayIndex i) 00814 { 00815 shape_type coordOffset; 00816 detail::ScanOrderToCoordinate<N>::exec(i, shape(), coordOffset); 00817 moveRelative(coordOffset); 00818 handles_.scanOrderIndex_ += i; 00819 return *this; 00820 } 00821 00822 CoupledScanOrderIterator & operator+=(const shape_type &coordOffset) 00823 { 00824 moveRelative(coordOffset); 00825 handles_.scanOrderIndex_ += detail::CoordinateToScanOrder<N>::exec(shape(), coordOffset); 00826 return *this; 00827 } 00828 00829 CoupledScanOrderIterator & operator-=(const shape_type &coordOffset) 00830 { 00831 return operator+=(-coordOffset); 00832 } 00833 00834 CoupledScanOrderIterator & operator--() 00835 { 00836 handles_.template decrement<dimension>(); 00837 handles_.decrementIndex(); 00838 return *this; 00839 } 00840 00841 CoupledScanOrderIterator operator--(int) 00842 { 00843 CoupledScanOrderIterator res(*this); 00844 --this; 00845 return res; 00846 } 00847 00848 CoupledScanOrderIterator & operator-=(MultiArrayIndex i) 00849 { 00850 return operator+=(-i); 00851 } 00852 00853 value_type operator[](MultiArrayIndex i) const 00854 { 00855 return *(CoupledScanOrderIterator(*this) += i); 00856 } 00857 00858 CoupledScanOrderIterator 00859 operator+(MultiArrayIndex d) const 00860 { 00861 return CoupledScanOrderIterator(*this) += d; 00862 } 00863 00864 CoupledScanOrderIterator 00865 operator-(MultiArrayIndex d) const 00866 { 00867 return CoupledScanOrderIterator(*this) -= d; 00868 } 00869 00870 CoupledScanOrderIterator operator+(const shape_type &coordOffset) const 00871 { 00872 return CoupledScanOrderIterator(*this) += coordOffset; 00873 } 00874 00875 CoupledScanOrderIterator operator-(const shape_type &coordOffset) const 00876 { 00877 return CoupledScanOrderIterator(*this) -= coordOffset; 00878 } 00879 00880 MultiArrayIndex 00881 operator-(CoupledScanOrderIterator const & r) const 00882 { 00883 return scanOrderIndex() - r.scanOrderIndex(); 00884 } 00885 00886 bool 00887 operator==(CoupledScanOrderIterator const & r) 00888 { 00889 return scanOrderIndex() == r.scanOrderIndex(); 00890 } 00891 00892 bool 00893 operator!=(CoupledScanOrderIterator const & r) const 00894 { 00895 return scanOrderIndex() != r.scanOrderIndex(); 00896 } 00897 00898 bool 00899 operator<(CoupledScanOrderIterator const & r) const 00900 { 00901 return scanOrderIndex() < r.scanOrderIndex(); 00902 } 00903 00904 bool 00905 operator<=(CoupledScanOrderIterator const & r) const 00906 { 00907 return scanOrderIndex() <= r.scanOrderIndex(); 00908 } 00909 00910 bool 00911 operator>(CoupledScanOrderIterator const & r) const 00912 { 00913 return scanOrderIndex() > r.scanOrderIndex(); 00914 } 00915 00916 bool 00917 operator>=(CoupledScanOrderIterator const & r) const 00918 { 00919 return scanOrderIndex() >= r.scanOrderIndex(); 00920 } 00921 00922 MultiArrayIndex scanOrderIndex() const 00923 { 00924 return handles_.scanOrderIndex(); 00925 } 00926 00927 typename value_type::shape_type const & point() const 00928 { 00929 return handles_.point(); 00930 } 00931 00932 typename value_type::shape_type const & shape() const 00933 { 00934 return handles_.shape(); 00935 } 00936 00937 reference operator*() 00938 { 00939 return handles_; 00940 } 00941 00942 const_reference operator*() const 00943 { 00944 return handles_; 00945 } 00946 00947 void restrictToSubarray(shape_type const & start, shape_type const & end) const 00948 { 00949 operator+=(-point()); 00950 handles_.restricToSubarray(start, end); 00951 } 00952 00953 CoupledScanOrderIterator getEndIterator() const 00954 { 00955 return operator+(prod(shape())); 00956 } 00957 00958 bool atBorder() const 00959 { 00960 return (handles_.neighborhoodType() != 0); 00961 } 00962 00963 unsigned int neighborhoodType() const 00964 { 00965 return handles_.neighborhoodType(); 00966 } 00967 00968 template<unsigned int TARGET_INDEX> 00969 typename CoupledHandleCast<TARGET_INDEX, value_type>::type::reference 00970 get() 00971 { 00972 return vigra::get<TARGET_INDEX>(handles_); 00973 } 00974 00975 template<unsigned int TARGET_INDEX> 00976 typename CoupledHandleCast<TARGET_INDEX, value_type>::type::const_reference 00977 get() const 00978 { 00979 return vigra::get<TARGET_INDEX>(handles_); 00980 } 00981 00982 protected: 00983 void reset() 00984 { 00985 handles_.template decrement<dimension>(shape()[dimension]); 00986 } 00987 00988 void inverseReset() 00989 { 00990 handles_.template increment<dimension>(shape()[dimension]); 00991 } 00992 00993 void moveRelative(typename value_type::shape_type const & coordOffset) 00994 { 00995 handles_.template increment<dimension>(coordOffset[dimension]); 00996 } 00997 00998 value_type handles_; 00999 }; 01000 01001 01002 template <unsigned int N, class List> 01003 struct ComposeCoupledHandle; 01004 01005 template <unsigned int N, class T, class TAIL> 01006 struct ComposeCoupledHandle<N, TypeList<T, TAIL> > 01007 { 01008 typedef typename ComposeCoupledHandle<N, TAIL>::type BaseType; 01009 typedef typename MultiArrayShape<N>::type shape_type; 01010 typedef CoupledHandle<T, BaseType> type; 01011 01012 template <class S> 01013 type exec(MultiArrayView<N, T, S> const & m, 01014 shape_type const & start, shape_type const & end, 01015 BaseType const & base) 01016 { 01017 return type(m.subarray(start, end).data(), m.stride(), base); 01018 } 01019 01020 template <class S> 01021 type exec(MultiArrayView<N, T, S> const & m, BaseType const & base) 01022 { 01023 return type(m.data(), m.stride(), base); 01024 } 01025 }; 01026 01027 template <unsigned int N> 01028 struct ComposeCoupledHandle<N, void> 01029 { 01030 typedef typename MultiArrayShape<N>::type shape_type; 01031 typedef CoupledHandle<shape_type, void> type; 01032 01033 type exec(shape_type const & shape) 01034 { 01035 return type(shape); 01036 } 01037 01038 type exec(shape_type const & start, shape_type const & end) 01039 { 01040 return type(end-start); 01041 } 01042 }; 01043 01044 template <unsigned int N, class T1=void, class T2=void, class T3=void, class T4=void, class T5=void> 01045 struct CoupledHandleType 01046 { 01047 // reverse the order to get the desired index order 01048 typedef typename MakeTypeList<T5, T4, T3, T2, T1>::type TypeList; 01049 typedef typename ComposeCoupledHandle<N, TypeList>::type type; 01050 }; 01051 01052 template <unsigned int N, class T1, class T2, class T3, class T4, class T5> 01053 struct CoupledHandleType<N, Multiband<T1>, T2, T3, T4, T5> 01054 { 01055 // reverse the order to get the desired index order 01056 typedef typename MakeTypeList<T5, T4, T3, T2, Multiband<T1> >::type TypeList; 01057 typedef typename ComposeCoupledHandle<N-1, TypeList>::type type; 01058 }; 01059 01060 /** Helper class to easliy get the type of a CoupledScanOrderIterator (and corresponding CoupledHandle) for up to five arrays of dimension N with element types T1,...,T5. 01061 */ 01062 template <unsigned int N, class T1=void, class T2=void, class T3=void, class T4=void, class T5=void> 01063 struct CoupledIteratorType 01064 { 01065 /** Type of the CoupledHandle.*/ 01066 typedef typename CoupledHandleType<N, T1, T2, T3, T4, T5>::type HandleType; 01067 01068 /** Type of the CoupledScanOrderIterator.*/ 01069 typedef CoupledScanOrderIterator<HandleType::dimensions, HandleType> type; 01070 }; 01071 01072 /** Returns a CoupledScanOrderIterator from shape to iterate over coordinates. 01073 */ 01074 template <int N> 01075 typename CoupledIteratorType<N>::type 01076 createCoupledIterator(TinyVector<MultiArrayIndex, N> const & shape) 01077 { 01078 typedef typename CoupledHandleType<N>::type P0; 01079 typedef CoupledScanOrderIterator<N, P0> IteratorType; 01080 01081 return IteratorType(P0(shape)); 01082 } 01083 01084 /** Returns a CoupledScanOrderIterator to simultaneously iterate over image m1 and its coordinates. 01085 */ 01086 template <unsigned int N1, class T1, class S1> 01087 typename CoupledIteratorType<N1, T1>::type 01088 createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1) 01089 { 01090 typedef typename CoupledHandleType<N1, T1>::type P1; 01091 typedef typename P1::base_type P0; 01092 typedef CoupledScanOrderIterator<P1::dimensions, P1> IteratorType; 01093 01094 return IteratorType(P1(m1, 01095 P0(m1.shape()))); 01096 } 01097 01098 /** Returns a CoupledScanOrderIterator to simultaneously iterate over images m1, m2 and their coordinates. 01099 */ 01100 template <unsigned int N1, class T1, class S1, 01101 unsigned int N2, class T2, class S2> 01102 typename CoupledIteratorType<N1, T1, T2>::type 01103 createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1, 01104 MultiArrayView<N2, T2, S2> const & m2) 01105 { 01106 typedef typename CoupledHandleType<N1, T1, T2>::type P2; 01107 typedef typename P2::base_type P1; 01108 typedef typename P1::base_type P0; 01109 typedef CoupledScanOrderIterator<P2::dimensions, P2> IteratorType; 01110 01111 return IteratorType(P2(m2, 01112 P1(m1, 01113 P0(m1.shape())))); 01114 } 01115 01116 /** Returns a CoupledScanOrderIterator to simultaneously iterate over images m1, m2, m3 and their coordinates. 01117 */ 01118 template <unsigned int N1, class T1, class S1, 01119 unsigned int N2, class T2, class S2, 01120 unsigned int N3, class T3, class S3> 01121 typename CoupledIteratorType<N1, T1, T2, T3>::type 01122 createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1, 01123 MultiArrayView<N2, T2, S2> const & m2, 01124 MultiArrayView<N3, T3, S3> const & m3) 01125 { 01126 typedef typename CoupledHandleType<N1, T1, T2, T3>::type P3; 01127 typedef typename P3::base_type P2; 01128 typedef typename P2::base_type P1; 01129 typedef typename P1::base_type P0; 01130 typedef CoupledScanOrderIterator<P3::dimensions, P3> IteratorType; 01131 01132 return IteratorType(P3(m3, 01133 P2(m2, 01134 P1(m1, 01135 P0(m1.shape()))))); 01136 } 01137 01138 /** Returns a CoupledScanOrderIterator to simultaneously iterate over images m1, m2, m3, m4 and their coordinates. 01139 */ 01140 template <unsigned int N1, class T1, class S1, 01141 unsigned int N2, class T2, class S2, 01142 unsigned int N3, class T3, class S3, 01143 unsigned int N4, class T4, class S4> 01144 typename CoupledIteratorType<N1, T1, T2, T3, T4>::type 01145 createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1, 01146 MultiArrayView<N2, T2, S2> const & m2, 01147 MultiArrayView<N3, T3, S3> const & m3, 01148 MultiArrayView<N4, T4, S4> const & m4) 01149 { 01150 typedef typename CoupledHandleType<N1, T1, T2, T3, T4>::type P4; 01151 typedef typename P4::base_type P3; 01152 typedef typename P3::base_type P2; 01153 typedef typename P2::base_type P1; 01154 typedef typename P1::base_type P0; 01155 typedef CoupledScanOrderIterator<P4::dimensions, P4> IteratorType; 01156 01157 return IteratorType(P4(m4, 01158 P3(m3, 01159 P2(m2, 01160 P1(m1, 01161 P0(m1.shape())))))); 01162 } 01163 01164 /** Returns a CoupledScanOrderIterator to simultaneously iterate over images m1, m2, m3, m4, m5 and their coordinates. 01165 */ 01166 template <unsigned int N1, class T1, class S1, 01167 unsigned int N2, class T2, class S2, 01168 unsigned int N3, class T3, class S3, 01169 unsigned int N4, class T4, class S4, 01170 unsigned int N5, class T5, class S5> 01171 typename CoupledIteratorType<N1, T1, T2, T3, T4, T5>::type 01172 createCoupledIterator(MultiArrayView<N1, T1, S1> const & m1, 01173 MultiArrayView<N2, T2, S2> const & m2, 01174 MultiArrayView<N3, T3, S3> const & m3, 01175 MultiArrayView<N4, T4, S4> const & m4, 01176 MultiArrayView<N5, T5, S5> const & m5) 01177 { 01178 typedef typename CoupledHandleType<N1, T1, T2, T3, T4, T5>::type P5; 01179 typedef typename P5::base_type P4; 01180 typedef typename P4::base_type P3; 01181 typedef typename P3::base_type P2; 01182 typedef typename P2::base_type P1; 01183 typedef typename P1::base_type P0; 01184 typedef CoupledScanOrderIterator<P1::dimensions, P5> IteratorType; 01185 01186 return IteratorType(P5(m5, 01187 P4(m4, 01188 P3(m3, 01189 P2(m2, 01190 P1(m1, 01191 P0(m1.shape()))))))); 01192 } 01193 01194 //@} 01195 01196 } // namespace vigra 01197 01198 #endif /* MULTI_ITERATOR_COUPLED_HXX_ */
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|