[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

vigra/matlab.hxx VIGRA

00001 /************************************************************************/
00002 /*                                                                      */
00003 /*                  Copyright 2008 by 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 /*    Software is furnished to do so, subject to the following          */
00016 /*    conditions:                                                       */
00017 /*    restriction, including without limitation the rights to use,      */
00018 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
00019 /*    sell copies of the Software, and to permit persons to whom the    */
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 
00037 #ifndef VIGRA_MATLAB_HXX
00038 #define VIGRA_MATLAB_HXX
00039 
00040 #include <string>
00041 
00042 #include "array_vector.hxx"
00043 #include "sized_int.hxx"
00044 #include "matrix.hxx"
00045 #include <map>
00046 #include <time.h>
00047 // This is needed with visual studio 10
00048 #ifdef _CHAR16T
00049 #define CHAR16_T
00050 #endif
00051 #include <mex.h>
00052 #include "matlab_FLEXTYPE.hxx"
00053 
00054 namespace vigra {
00055 
00056 namespace matlab {
00057 
00058 template <class T>
00059 struct ValueType;
00060 
00061 #define VIGRA_MATLAB_VALUETYPE_UTIL(type, functionName, typeID, matTypeName) \
00062 template <> \
00063 struct ValueType<type> \
00064 { \
00065     static bool check(mxArray const * t) \
00066     { \
00067         return mxIs##functionName(t); \
00068     } \
00069     \
00070     static mxClassID const classID = typeID; \
00071     \
00072     static std::string typeName() \
00073     { \
00074         return #matTypeName; \
00075     } \
00076 };
00077 
00078 VIGRA_MATLAB_VALUETYPE_UTIL(double, Double, mxDOUBLE_CLASS, double)
00079 VIGRA_MATLAB_VALUETYPE_UTIL(float, Single, mxSINGLE_CLASS, single)
00080 VIGRA_MATLAB_VALUETYPE_UTIL(Int8,  Int8, mxINT8_CLASS, int8)
00081 VIGRA_MATLAB_VALUETYPE_UTIL(UInt8,  Uint8, mxUINT8_CLASS, uint8)
00082 VIGRA_MATLAB_VALUETYPE_UTIL(Int16, Int16, mxINT16_CLASS, int16)
00083 VIGRA_MATLAB_VALUETYPE_UTIL(UInt16, Uint16, mxUINT16_CLASS, uint16)
00084 
00085 #if VIGRA_BITSOF_INT == 32
00086 VIGRA_MATLAB_VALUETYPE_UTIL(int, Int32, mxINT32_CLASS, int32)
00087 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned int, Uint32, mxUINT32_CLASS, uint32)
00088 #elif VIGRA_BITSOF_INT == 64
00089 VIGRA_MATLAB_VALUETYPE_UTIL(int, Int64, mxINT64_CLASS, int64)
00090 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned int, Uint64, mxUINT64_CLASS, uint64)
00091 #endif
00092 
00093 #if VIGRA_BITSOF_LONG == 32
00094 VIGRA_MATLAB_VALUETYPE_UTIL(long, Int32, mxINT32_CLASS, int32)
00095 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long, Uint32, mxUINT32_CLASS, uint32)
00096 #elif VIGRA_BITSOF_LONG == 64
00097 VIGRA_MATLAB_VALUETYPE_UTIL(long, Int64, mxINT64_CLASS, int64)
00098 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long, Uint64, mxUINT64_CLASS, uint64)
00099 #endif
00100 
00101 #if VIGRA_BITSOF_LONG_LONG == 32
00102 VIGRA_MATLAB_VALUETYPE_UTIL(long long, Int32, mxINT32_CLASS, int32)
00103 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long long, Uint32, mxUINT32_CLASS, uint32)
00104 #elif VIGRA_BITSOF_LONG_LONG == 64
00105 VIGRA_MATLAB_VALUETYPE_UTIL(long long, Int64, mxINT64_CLASS, int64)
00106 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long long, Uint64, mxUINT64_CLASS, uint64)
00107 #endif
00108 
00109 #undef VIGRA_MATLAB_VALUETYPE_UTIL
00110 
00111 class ConstStructArray
00112 {
00113   protected:
00114     mxArray * matPointer_;
00115 
00116   public:
00117 
00118     struct Proxy
00119     {
00120         mxArray * matPointer_;
00121         int index_;
00122 
00123         Proxy(mxArray * matPointer, int index)
00124         : matPointer_(matPointer),
00125           index_(index)
00126         {}
00127 
00128         operator const mxArray *() const
00129         {
00130             return mxGetFieldByNumber(matPointer_, 0, index_);
00131         }
00132     };
00133 
00134     ConstStructArray(const mxArray * matPointer = 0)
00135     : matPointer_(const_cast<mxArray *>(matPointer))
00136     {
00137         if(matPointer != 0 && !mxIsStruct(matPointer))
00138             mexErrMsgTxt("StructArray(mxArray *): Argument must be a Matlab struct array.");
00139     }
00140 
00141     Proxy operator[](const char * field_name) const
00142     {
00143         if(matPointer_ == 0)
00144             mexErrMsgTxt("StructArray::operator[]: Cannot access uninitialized struct array.");
00145 
00146         int i = mxGetFieldNumber(matPointer_, field_name);
00147         if(i == -1)
00148             mexErrMsgTxt("StructArray::operator[]: Unknown field name.");
00149 
00150         return Proxy(matPointer_, i);
00151     }
00152 
00153     Proxy operator[](std::string field_name) const
00154     {
00155         return operator[](field_name.c_str());
00156     }
00157 
00158     bool isValid() const
00159     {
00160         return matPointer_ != 0;
00161     }
00162 
00163     bool isValid(const char * field_name) const
00164     {
00165         return isValid() && mxGetFieldNumber(matPointer_, field_name) != -1;
00166     }
00167 
00168     bool isValid(std::string field_name) const
00169     {
00170         return isValid(field_name.c_str());
00171     }
00172 };
00173 
00174 class ConstCellArray
00175 {
00176   protected:
00177     mxArray * matPointer_;
00178     int size_;
00179 
00180   public:
00181 
00182     struct Proxy
00183     {
00184         mxArray * matPointer_;
00185         int index_;
00186 
00187         Proxy(mxArray * matPointer, int index)
00188         : matPointer_(matPointer),
00189           index_(index)
00190         {}
00191 
00192         operator const mxArray *() const
00193         {
00194             return mxGetCell(matPointer_, index_);
00195         }
00196     };
00197 
00198     ConstCellArray(const mxArray * matPointer = 0)
00199     : matPointer_(const_cast<mxArray *>(matPointer)),
00200       size_(0)
00201     {
00202         if(matPointer != 0 && !mxIsCell(matPointer))
00203             mexErrMsgTxt("CellArray(mxArray *): Argument must be a Matlab cell array.");
00204         if(matPointer != 0)
00205             size_ = static_cast<int>(mxGetNumberOfElements(matPointer));
00206         else
00207             size_ = -1;
00208     }
00209 
00210     Proxy operator[](int i) const
00211     {
00212         if(!isValid(i))
00213             mexErrMsgTxt("CellArray::operator[]: Index out of range.");
00214         return Proxy(matPointer_, i);
00215     }
00216 
00217     int size() const
00218     {
00219         return size_;
00220     }
00221 
00222     bool isValid( int i ) const
00223     {
00224         return i >= 0 && i < size_;
00225     }
00226 
00227 };
00228 
00229 class CellArray
00230 : public ConstCellArray
00231 {
00232   public:
00233 
00234     struct Proxy
00235     : public ConstCellArray::Proxy
00236     {
00237         Proxy(mxArray * matPointer, int index)
00238         : ConstCellArray::Proxy(matPointer, index)
00239         {}
00240 
00241         void operator=(mxArray * v)
00242         {
00243             mxDestroyArray(mxGetCell(matPointer_, index_));
00244             mxSetCell(matPointer_, index_, v);
00245         }
00246     };
00247 
00248     CellArray(const mxArray * matPointer)
00249     : ConstCellArray(matPointer)
00250     {}
00251 
00252     Proxy operator[](int i)
00253     {
00254         if(!isValid(i))
00255             mexErrMsgTxt("CellArray::operator[]: Index out of range.");
00256         return Proxy(matPointer_, i);
00257     }
00258 
00259     ConstCellArray::Proxy operator[](int i) const
00260     {
00261         if(!isValid(i))
00262             mexErrMsgTxt("CellArray::operator[]: Index out of range.");
00263         return ConstCellArray::Proxy(matPointer_, i);
00264     }
00265 };
00266 
00267 
00268 
00269 
00270 
00271 template <class T, unsigned int SIZE>
00272 TinyVectorView<T, SIZE>
00273 getTinyVector(mxArray const * t)
00274 {
00275     if(!ValueType<T>::check(t))
00276     {
00277         std::string msg = std::string("Input array must have type ") +
00278                           ValueType<T>::typeName() + ".";
00279         mexErrMsgTxt(msg.c_str());
00280     }
00281     if(SIZE != mxGetNumberOfElements(t))
00282     {
00283         mexErrMsgTxt("getTinyVector(): Input array has wrong number of elements.");
00284     }
00285 
00286     return TinyVectorView<T, SIZE>((T *)mxGetData(t));
00287 }
00288 
00289 template <unsigned int SIZE>
00290 typename MultiArrayShape<SIZE>::type
00291 getShape(mxArray const * t)
00292 {
00293     if(!ValueType<Int32>::check(t))
00294     {
00295         std::string msg = std::string("Input array must have type 'int32'.");
00296         mexErrMsgTxt(msg.c_str());
00297     }
00298     if(SIZE != mxGetNumberOfElements(t))
00299     {
00300         mexErrMsgTxt("getShape(): Input array has wrong number of elements.");
00301     }
00302     TinyVectorView<Int32, SIZE> res((MultiArrayIndex *)mxGetData(t));
00303     return typename MultiArrayShape<SIZE>::type(res);
00304 }
00305 
00306 template <int DIM, class T>
00307 MultiArrayView<DIM, T>
00308 getMultiArray(mxArray const * t)
00309 {
00310     typedef typename MultiArrayView<DIM, T>::difference_type Shape;
00311 
00312     if(!ValueType<T>::check(t))
00313     {
00314         std::string msg = std::string("getMultiArray(): Input array must have type ") +
00315                           ValueType<T>::typeName() + ".";
00316         mexErrMsgTxt(msg.c_str());
00317     }
00318 
00319     Shape shape;
00320     if(DIM > 1)
00321     {
00322         int mdim = mxGetNumberOfDimensions(t);
00323         if(DIM < mdim)
00324         {
00325             mexErrMsgTxt("getMultiArray(): Input array has too many dimensions.");
00326         }
00327         const mwSize * matlabShape = mxGetDimensions(t);
00328         for(int k=0; k<mdim; ++k)
00329         {
00330             shape[k] = static_cast<typename Shape::value_type>(matlabShape[k]);
00331         }
00332         for(int k=mdim; k<DIM; ++k)
00333         {
00334             shape[k] = 1;
00335         }
00336     }
00337     else
00338     {
00339         shape[0] = static_cast<typename Shape::value_type>(mxGetNumberOfElements(t));
00340     }
00341     return MultiArrayView<DIM, T>(shape, (T *)mxGetData(t));
00342 }
00343 
00344 template <int DIM, class T>
00345 MultiArrayView<DIM, T>
00346 createMultiArray(typename MultiArrayShape<DIM>::type const & shape, mxArray * & t)
00347 {
00348     mwSize matlabShape[DIM];
00349     for(int k=0; k<DIM; ++k)
00350         matlabShape[k] = static_cast<mwSize>(shape[k]);
00351     t = mxCreateNumericArray(DIM, matlabShape, ValueType<T>::classID, mxREAL);
00352 
00353     return MultiArrayView<DIM, T>(shape, (T *)mxGetData(t));
00354 }
00355 
00356 template <int DIM, class T>
00357 MultiArrayView<DIM, T>
00358 createMultiArray(typename MultiArrayShape<DIM>::type const & shape, CellArray::Proxy t)
00359 {
00360     mwSize matlabShape[DIM];
00361     for(int k=0; k<DIM; ++k)
00362         matlabShape[k] = static_cast<mwSize>(shape[k]);
00363     t = mxCreateNumericArray(DIM, matlabShape, ValueType<T>::classID, mxREAL);
00364 
00365     return MultiArrayView<DIM, T>(shape, (T *)mxGetData(t));
00366 }
00367 
00368 template <class T>
00369 inline MultiArrayView<1, T>
00370 getArray(mxArray const * t)
00371 {
00372     return getMultiArray<1, T>(t);
00373 }
00374 
00375 template <class T>
00376 inline MultiArrayView<1, T>
00377 createArray(MultiArrayIndex size, mxArray * & t)
00378 {
00379     return createMultiArray<1, T>(MultiArrayShape<1>::type(size), t);
00380 }
00381 
00382 template <class T>
00383 inline MultiArrayView<1, T>
00384 createArray(MultiArrayIndex size, CellArray::Proxy t)
00385 {
00386     return createMultiArray<1, T>(MultiArrayShape<1>::type(size), t);
00387 }
00388 
00389 template <class T>
00390 MultiArrayView<2, T>
00391 getMatrix(mxArray const * t)
00392 {
00393     typedef typename MultiArrayView<2, T>::difference_type Shape;
00394 
00395     if(!ValueType<T>::check(t))
00396     {
00397         std::string msg = std::string("getMatrix(): Input matrix must have type ") +
00398                           ValueType<T>::typeName() + ".";
00399         mexErrMsgTxt(msg.c_str());
00400     }
00401 
00402     if(2 != mxGetNumberOfDimensions(t))
00403         mexErrMsgTxt("getMatrix(): Input matrix must have 2 dimensions.");
00404 
00405     const mwSize * matlabShape = mxGetDimensions(t);
00406     Shape shape(static_cast<MultiArrayIndex>(matlabShape[0]),
00407                 static_cast<MultiArrayIndex>(matlabShape[1]));
00408 
00409     return MultiArrayView<2, T>(shape, (T *)mxGetData(t));
00410 }
00411 
00412 template <class T>
00413 MultiArrayView<2, T>
00414 createMatrix(mwSize rowCount, mwSize columnCount, mxArray * & t)
00415 {
00416     typedef typename MultiArrayView<2, T>::difference_type Shape;
00417 
00418     Shape shape(rowCount, columnCount);
00419     t = mxCreateNumericMatrix(rowCount, columnCount, ValueType<T>::classID, mxREAL);
00420 
00421     return MultiArrayView<2, T>(shape, (T *)mxGetData(t));
00422 }
00423 
00424 template <class T>
00425 MultiArrayView<2, T>
00426 createMatrix(mwSize rowCount, mwSize columnCount, CellArray::Proxy t)
00427 {
00428     typedef typename MultiArrayView<2, T>::difference_type Shape;
00429 
00430     Shape shape(rowCount, columnCount);
00431     t = mxCreateNumericMatrix(rowCount, columnCount, ValueType<T>::classID, mxREAL);
00432 
00433     return MultiArrayView<2, T>(shape, (T *)mxGetData(t));
00434 }
00435 
00436 template <class T>
00437 BasicImageView<T>
00438 getImage(mxArray const * t)
00439 {
00440     if(!ValueType<T>::check(t))
00441     {
00442         std::string msg = std::string("getImage(): Input matrix must have type ") +
00443                           ValueType<T>::typeName() + ".";
00444         mexErrMsgTxt(msg.c_str());
00445     }
00446 
00447     if(2 != mxGetNumberOfDimensions(t))
00448         mexErrMsgTxt("getImage(): Input matrix must have 2 dimensions.");
00449 
00450     const mwSize * matlabShape = mxGetDimensions(t);
00451     return BasicImageView<T>((T *)mxGetData(t), static_cast<int>(matlabShape[0]),
00452                                                 static_cast<int>(matlabShape[1]));
00453 }
00454 
00455 template <class T>
00456 BasicImageView<T>
00457 createImage(mwSize width, mwSize height, mxArray * & t)
00458 {
00459     t = mxCreateNumericMatrix(width, height, ValueType<T>::classID, mxREAL);
00460 
00461     return BasicImageView<T>((T *)mxGetData(t), width, height);
00462 }
00463 
00464 template <class T>
00465 BasicImageView<T>
00466 createImage(mwSize width, mwSize height, CellArray::Proxy t)
00467 {
00468     t = mxCreateNumericMatrix(width, height, ValueType<T>::classID, mxREAL);
00469 
00470     return BasicImageView<T>((T *)mxGetData(t), width, height);
00471 }
00472 
00473 inline ConstCellArray
00474 getCellArray(mxArray const * t)
00475 {
00476     return ConstCellArray(t);
00477 }
00478 
00479 inline CellArray
00480 createCellArray(mwSize size, mxArray * & t)
00481 {
00482     mwSize matSize[] = { size };
00483     t = mxCreateCellArray(1, matSize);
00484 
00485     return CellArray(t);
00486 }
00487 
00488 inline CellArray
00489 createCellArray(mwSize size, CellArray::Proxy t)
00490 {
00491     mwSize matSize[] = { size };
00492     t = mxCreateCellArray(1, matSize);
00493 
00494     return CellArray(t);
00495 }
00496 
00497 inline ConstStructArray
00498 getStructArray(mxArray const * t)
00499 {
00500     return ConstStructArray(t);
00501 }
00502 
00503 template<class T>
00504 T
00505 getScalar(mxArray const * t)
00506 {
00507     if(mxIsEmpty(t))
00508         mexErrMsgTxt("getScalar() on empty input.");
00509     if(!mxIsNumeric(t) && !mxIsLogical(t))
00510         mexErrMsgTxt("getScalar(): argument is not numeric.");
00511     return static_cast<T>(mxGetScalar(t));
00512 }
00513 
00514 template<class T>
00515 mxArray *
00516 createScalar(T v)
00517 {
00518     mxArray * m;
00519     createMatrix<double>(1, 1, m)(0,0) = static_cast<double>(v);
00520     return m;
00521 }
00522 
00523 inline std::string
00524 getString(mxArray const * t)
00525 {
00526     if(mxIsEmpty(t))
00527         mexErrMsgTxt("getString() on empty input.");
00528     if(!mxIsChar(t))
00529         mexErrMsgTxt("getString(): argument is not a string.");
00530     int size = static_cast<int>(mxGetNumberOfElements(t) + 1);
00531     ArrayVector<char> buf(size);
00532     mxGetString(t, buf.begin(), size);
00533     return std::string(buf.begin());
00534 }
00535 
00536 
00537 
00538 class CompileTimeError;
00539 
00540 namespace detail {
00541 
00542 class Required
00543 {
00544   public:
00545     void argumentWasProvided() const { /* empty because required arguments are always provided */ }
00546 };
00547 
00548 
00549 template<class T>
00550 class DefaultImpl
00551 {
00552   public:
00553 
00554     T defaultValue_;
00555     mutable bool * argumentWasProvided_;
00556 
00557     DefaultImpl(T v, bool * argFlag = 0)
00558     : defaultValue_(v),
00559       argumentWasProvided_(argFlag)
00560     {
00561         if(argumentWasProvided_ != 0)
00562             *argumentWasProvided_ = false;
00563     }
00564 
00565     void argumentWasProvided() const
00566     {
00567         if(argumentWasProvided_ != 0)
00568             *argumentWasProvided_ = true;
00569     }
00570 };
00571 
00572 class OptionalImpl
00573 {
00574   public:
00575     mutable bool * argumentWasProvided_;
00576 
00577     OptionalImpl(bool * argFlag = 0)
00578     : argumentWasProvided_(argFlag)
00579     {
00580         if(argumentWasProvided_ != 0)
00581             *argumentWasProvided_ = false;
00582     }
00583 
00584     void argumentWasProvided() const
00585     {
00586         if(argumentWasProvided_ != 0)
00587             *argumentWasProvided_ = true;
00588     }
00589 };
00590 
00591 } // namespace detail
00592 
00593 inline detail::Required v_required()
00594 {
00595     return detail::Required();
00596 }
00597 
00598 template<class T>
00599 inline detail::DefaultImpl<T> v_default(T in)
00600 {
00601     return detail::DefaultImpl<T>(in);
00602 }
00603 
00604 template<class T>
00605 inline detail::DefaultImpl<T> v_default(T in, bool & argFlag)
00606 {
00607     return detail::DefaultImpl<T>(in, &argFlag);
00608 }
00609 
00610 inline detail::OptionalImpl v_optional()
00611 {
00612     return detail::OptionalImpl();
00613 }
00614 
00615 inline detail::OptionalImpl v_optional(bool& argFlag)
00616 {
00617     return detail::OptionalImpl(&argFlag);
00618 }
00619 
00620 // TODO:
00621 //    * handle rgb images
00622 //    * handle complex matrices
00623 //    * handle sparse matrices
00624 
00625 class InputArray
00626 {
00627     int size_;
00628     const mxArray ** data_;
00629 
00630     std::string createErrMsg(std::string name)
00631     {
00632         std::string s1;
00633         s1 =  "Required input '" + name + "' not found in option struct!";
00634         return s1;
00635     }
00636     std::string createErrMsg(int pos)
00637     {
00638         char tmp[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
00639         std::string oi(1, tmp[pos%10]);
00640         std::string s1  = "Required input in signature of function at position: '"+ oi+"' has not been supplied";
00641         return s1;
00642     }
00643 
00644 
00645   public:
00646     ConstStructArray options_;
00647 
00648     /* Local Typedefs */
00649     typedef const mxArray * value_type;
00650     typedef value_type & reference;
00651     typedef value_type const & const_reference;
00652     typedef value_type * pointer;
00653     typedef value_type const * const_pointer;
00654     typedef int size_type;
00655     typedef int difference_type;
00656 
00657     /*Constructor*/
00658     InputArray(size_type size, pointer data)
00659     : size_(size),
00660       data_(data),
00661       options_(isValid(size-1) && mxIsStruct(data_[size-1])
00662                  ? data_[size-1]
00663                  : 0)
00664     {}
00665 
00666     /*Operators*/
00667     const_reference operator[]( difference_type i ) const
00668     {
00669         if(!isValid(i))
00670             mexErrMsgTxt("Too few input arguments.");
00671         return data_[i];
00672     }
00673 
00674     value_type operator[]( std::string name) const
00675     {
00676         std::string errMsg = "Not Found " + name +" in OptionStruct or OptionStruct not set";
00677         if(!isValid(name))
00678             mexErrMsgTxt(errMsg.c_str());
00679         return options_[name];
00680     }
00681 
00682 
00683     /*Some More Helper Func*/
00684     size_type size() const
00685     {
00686         return size_;
00687     }
00688 
00689     bool isValid( difference_type i ) const
00690     {
00691         return i >= 0 && i < size_;
00692     }
00693 
00694     bool isValid(std::string name) const
00695     {
00696         return options_.isValid(name);
00697     }
00698 
00699     bool isEmpty(difference_type i) const
00700     {
00701         return mxIsEmpty(data_[i]);
00702     }
00703 
00704     bool isEmpty(std::string name) const
00705     {
00706         return mxIsEmpty(options_[name]);
00707     }
00708 
00709     bool hasData(difference_type i) const
00710     {
00711         return isValid(i) && !isEmpty(i);
00712     }
00713 
00714     bool hasData(std::string name) const
00715     {
00716         return isValid(name) && !isEmpty(name);
00717     }
00718 
00719     template<class Place>
00720     mxClassID typeOf(Place posOrName)
00721     {
00722         return mxGetClassID((*this)[posOrName]);
00723     }
00724 
00725     /*Action to take if value not set*/
00726     template <class T, class U, class Place>
00727     T errorOrDefault(detail::DefaultImpl<U> const & o, Place posOrName)
00728     {
00729         return o.defaultValue_;
00730     }
00731 
00732     template <class T, class Place>
00733     T errorOrDefault(detail::OptionalImpl, Place posOrName)
00734     {
00735         return T();
00736     }
00737 
00738     template <class T, class Place>
00739     T errorOrDefault(detail::Required r, Place posOrName)
00740     {
00741         std::string a = createErrMsg(posOrName);
00742         mexErrMsgTxt( a.c_str());
00743         return T();
00744     }
00745 
00746     /*getter Func*/
00747     template <class Place, class ReqType>
00748     int getEnum(Place posOrName, ReqType req, std::map<std::string, int> const & converter)
00749     {
00750         if(!hasData(posOrName))
00751         {
00752             return errorOrDefault<int>(req, posOrName);
00753         }
00754         std::string enumAsString = matlab::getString((*this)[posOrName]);
00755         typename std::map<std::string, int>::const_iterator m = converter.find(enumAsString);
00756         if(m == converter.end())
00757         {
00758             std::string msg = std::string("Unknown option: ") + enumAsString + ".";
00759             mexErrMsgTxt(msg.c_str());
00760         }
00761 
00762         req.argumentWasProvided();
00763         return (*m).second;
00764     }
00765 
00766 
00767     /*String Type*/
00768     template <class Place, class ReqType>
00769     std::string getString(Place posOrName, ReqType req)
00770     {
00771         if(!hasData(posOrName))
00772         {
00773             return errorOrDefault<std::string>(req, posOrName);
00774         }
00775         else
00776         {
00777             req.argumentWasProvided();
00778             return matlab::getString((*this)[posOrName]);
00779         }
00780     }
00781 
00782     /*Scalar Type*/
00783     template <class T,class Place, class ReqType>
00784     T getScalar(Place posOrName, ReqType req)
00785     {
00786         if(!hasData(posOrName))
00787         {
00788             return errorOrDefault<T>(req, posOrName);
00789         }
00790         else
00791         {
00792             req.argumentWasProvided();
00793             return matlab::getScalar<T>((*this)[posOrName]);
00794         }
00795     }
00796 
00797 
00798     template <class T, class Place, class ReqType, class minClass, class maxClass>
00799     T getScalarMinMax(Place posOrName, ReqType req, minClass min_, maxClass max_)
00800     {
00801         T temp = this->getScalar<T>(posOrName, req);
00802         if (!is_in_range(temp, min_, max_))
00803             mexErrMsgTxt("Value out of bounds.");
00804         return temp;
00805     }
00806 
00807     template <class T, class Place, class ReqType, class iteratorType>
00808     T getScalarVals(Place posOrName, ReqType req, iteratorType begin_, iteratorType end_)
00809     {
00810         T temp = this->getScalar<T>(posOrName, req);
00811         for(iteratorType iter = begin_; iter != end_; ++iter)
00812         {
00813             if((*iter) == temp) return temp;
00814         }
00815         mexErrMsgTxt("Value not allowed");
00816     }
00817 
00818 
00819 
00820     template <class T, class Place, class ReqType, class iteratorType>
00821     T getScalarVals2D3D(Place posOrName, ReqType req, iteratorType begin2D_, iteratorType end2D_,
00822                                                      iteratorType begin3D_, iteratorType end3D_,
00823                                                      int dimVar)
00824     {
00825         T temp = this->getScalar<T>(posOrName, req);
00826         switch(dimVar)
00827         {
00828             case 2:
00829                 for(iteratorType iter = begin2D_; iter != end2D_; ++iter)
00830                 {
00831                     if((*iter) == temp) return temp;
00832                 }
00833                 break;
00834             case 3:
00835                 for(iteratorType iter = begin3D_; iter != end3D_; ++iter)
00836                 {
00837                     if((*iter) == temp) return temp;
00838                 }
00839                 break;
00840             default:
00841                 mexErrMsgTxt("dimVar specified must be 2 or 3");
00842         }
00843         mexErrMsgTxt("Value not allowed");
00844     }
00845 
00846     template <class Place, class ReqType>
00847     bool getBool(Place posOrName, ReqType req)
00848     {
00849         return this->getScalarMinMax<int>(posOrName, req, 0, 1) != 0;
00850     }
00851 
00852     /*Array Type*/
00853     template <unsigned int N, class T, class Place, class ReqType>
00854     MultiArrayView<N,T> getMultiArray(Place posOrName, ReqType req)
00855     {
00856         if(!hasData(posOrName))
00857         {
00858             return errorOrDefault< MultiArrayView<N,T> >(req, posOrName);
00859         }
00860         else
00861         {
00862             req.argumentWasProvided();
00863             value_type temp = (*this)[posOrName];
00864             return matlab::getMultiArray<N,T>(temp);
00865         }
00866     }
00867 
00868     template < class T, class Place, class ReqType>
00869     BasicImageView<T> getImage(Place posOrName, ReqType req)
00870     {
00871         if(!hasData(posOrName))
00872         {
00873             return errorOrDefault<BasicImageView<T> >(req, posOrName);
00874         }
00875         else
00876         {
00877             req.argumentWasProvided();
00878             value_type temp = (*this)[posOrName];
00879             return matlab::getImage<T>(temp);
00880         }
00881     }
00882 
00883     template<class T,unsigned int sze, class Place, class ReqType>
00884     TinyVectorView< T, sze> getTinyVector(Place posOrName, ReqType req)
00885     {
00886         if(!hasData(posOrName))
00887         {
00888             return errorOrDefault<TinyVectorView< T, sze> >(req, posOrName);
00889         }
00890         else
00891         {
00892             req.argumentWasProvided();
00893             value_type temp = (*this)[posOrName];
00894             return matlab::getTinyVector< T, sze>(temp);
00895         }
00896     }
00897 
00898     template< unsigned int sze, class Place, class ReqType>
00899     TinyVectorView<MultiArrayIndex, sze> getShape(Place posOrName, ReqType req)
00900     {
00901         if(!hasData(posOrName))
00902         {
00903             return errorOrDefault<TinyVectorView<MultiArrayIndex, sze> >(req, posOrName);
00904         }
00905         else
00906         {
00907             req.argumentWasProvided();
00908             value_type temp = (*this)[posOrName];
00909             return matlab::getShape<sze>(temp);
00910         }
00911     }
00912 
00913 
00914     template< class Place, class ReqType>
00915     int getDimOfInput(Place posOrName, ReqType req)
00916     {
00917         if(!hasData(posOrName))
00918         {
00919             return errorOrDefault<int>(req, posOrName);
00920         }
00921         else
00922         {
00923             req.argumentWasProvided();
00924             return mxGetNumberOfDimensions((*this)[posOrName]);
00925         }
00926     }
00927 
00928     template<class ReqType>
00929     ConstCellArray getCellArray(int posOrName, ReqType req)
00930     {
00931         if(!hasData(posOrName))
00932         {
00933             return errorOrDefault<ConstCellArray>(req, posOrName);
00934         }
00935         else
00936         {
00937             req.argumentWasProvided();
00938             value_type temp = (*this)[posOrName];
00939             return matlab::getCellArray(temp);
00940         }
00941     }
00942 
00943     template<class ReqType>
00944     ConstCellArray getCellArray(std::string posOrName, ReqType req)
00945     {
00946         CompileTimeError ERROR__Const_Cell_Array_May_Not_Be_In_Option_Struct;
00947         return ConstCellArray(); //avoid compiler warning
00948     }
00949 
00950 };
00951 
00952 class OutputArray
00953 {
00954     int size_;
00955     mxArray ** data_;
00956     std::string createErrMsgOut(int pos)
00957     {
00958         char tmp[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
00959         std::string oi(1, tmp[pos%10]);
00960         std::string s1 =  "Required Output at position: '" + oi + "' has not been supplied";
00961         return s1;
00962     }
00963   public:
00964 
00965     typedef mxArray * value_type;
00966     typedef value_type & reference;
00967     typedef value_type const & const_reference;
00968     typedef value_type * pointer;
00969     typedef value_type const * const_pointer;
00970     typedef int size_type;
00971     typedef int difference_type;
00972 
00973     OutputArray(size_type size, pointer data)
00974     : size_(size),
00975       data_(data)
00976     {}
00977 
00978     reference operator[]( difference_type i )
00979     {
00980         if(!isValid(i))
00981             mexErrMsgTxt("Too few output arguments.");
00982         return data_[i];
00983     }
00984 
00985     const_reference operator[]( difference_type i ) const
00986     {
00987         if(!isValid(i))
00988             mexErrMsgTxt("Too few output arguments.");
00989         return data_[i];
00990     }
00991 
00992     size_type size() const
00993     {
00994         return size_;
00995     }
00996 
00997     bool isValid( difference_type i ) const
00998     {
00999         return i >= 0 && i < size_;
01000     }
01001 
01002     bool isEmpty(difference_type i){
01003         return mxIsEmpty(data_[i]);
01004     }
01005 
01006     template <class T>
01007     T errorOrDefault(detail::OptionalImpl const & o, int Pos)
01008     {
01009         return T();
01010     }
01011 
01012     template <class T>
01013     T errorOrDefault(detail::Required r, int Pos)
01014     {
01015         mexErrMsgTxt(createErrMsgOut(Pos).c_str());
01016         return T();
01017     }
01018 
01019     /* creating func */
01020     template <unsigned int DIM, class T, class ReqType>
01021     MultiArrayView<DIM, T> createMultiArray(int pos,ReqType req,
01022                                             const TinyVector<int, DIM>  & shape)
01023     {
01024         if(!isValid(pos))
01025             return errorOrDefault<MultiArrayView<DIM, T> >(req, pos);
01026         req.argumentWasProvided();
01027         return matlab::createMultiArray<DIM, T>(shape, (*this)[pos]);
01028     }
01029 
01030     template <class T, class ReqType>
01031     BasicImageView<T> createImage(int pos, ReqType req,
01032                                     mwSize width, mwSize height)
01033     {
01034         if(!isValid(pos))
01035             return errorOrDefault<BasicImageView<T> >(req, pos);
01036         req.argumentWasProvided();
01037         return matlab::createImage<T>(width, height, (*this)[pos]);
01038     }
01039 
01040     template <class T, class ReqType>
01041     BasicImageView<T> createImage(  int pos, ReqType req,
01042                                     typename MultiArrayShape<2>::type const & shape)
01043     {
01044         return createImage<T>(pos, req, shape[1], shape[0]);
01045     }
01046 
01047     template <class T, class ReqType>
01048     T* createScalar(int pos, ReqType req)
01049     {
01050         if(!isValid(pos))
01051             return errorOrDefault<T*>(req, pos);
01052         req.argumentWasProvided();
01053         BasicImageView<T> temp = matlab::createImage<T>(1, 1, (*this)[pos]);
01054         return &temp(0,0);
01055     }
01056 
01057     template <class T, class ReqType>
01058     void createScalar(int pos, ReqType req, T val)
01059     {
01060         if(!isValid(pos))
01061         {
01062             errorOrDefault<T>(req, pos);
01063             return;
01064         }
01065         req.argumentWasProvided();
01066         BasicImageView<T> temp = matlab::createImage<T>(1, 1, (*this)[pos]);
01067         temp(0,0) = val;
01068     }
01069 
01070     template <class ReqType>
01071     ConstCellArray createCellArray(int pos, ReqType req, mwSize sze)
01072     {
01073         if(!isValid(pos))
01074             return errorOrDefault<ConstCellArray>(req, pos);
01075         return matlab::createCellArray(sze, (*this)[pos]);
01076     }
01077 };
01078 
01079 
01080 
01081 /***********************************
01082 Rahuls code starts here
01083 ************************************/
01084 using namespace vigra;
01085 
01086 
01087 /*++++++++++++++++++++++++++HELPERFUNC+++++++++++++++++++++++++++++++*
01088  * This is used for better readability of the test cases            .
01089  * Nothing to be done here.
01090  *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
01091 int cantorPair(int x, int y){
01092         return (int)(((x+y)*(x+y+1))/2+y);
01093 }
01094 
01095 int cantorPair(int x, int y, int z){
01096         return cantorPair(cantorPair(x,y),z);
01097 }
01098 
01099 template <int x, int y>
01100 struct cP{
01101     enum { value = (int)(((x+y)*(x+y+1))/2+y)};
01102 };
01103 
01104 template <int x, int y, int z>
01105 struct cP3{
01106     enum { value = cP<cP<x, y>::value, z>::value};
01107 };
01108 
01109 template <class T>
01110 inline bool is_in_range(T in, T min, T max)
01111 {
01112     return (in >= min && in <= max);
01113 }
01114 template<class T>
01115 inline bool is_in_range(T in, std::string min, T max)
01116 {
01117     return(in <= max);
01118 }
01119 
01120 template<class T>
01121 inline bool is_in_range(T in, T min, std::string max)
01122 {
01123     return (in >= min);
01124 }
01125 
01126 
01127 
01128 //Wrapper classes to STL-Map for use as a sparse array.
01129 
01130 //This is used for the ordering of the map. Lexicographical ordering of the index pairs.
01131 struct ShapeCmp {
01132   bool operator()( TinyVector<int,2> s1, TinyVector<int,2>  s2 ) const {
01133     if(s1[0] != s2[0]){
01134         return (s1[0] < s2[0]);
01135     } else {
01136         return s1[1] < s2[1];
01137     }
01138   }
01139 };
01140 
01141 template<class T>
01142 class SparseArray
01143 {
01144 
01145     std::map<TinyVector<int,2>, T,ShapeCmp> data;
01146     int width, length;
01147 
01148     public:
01149     void assign(int i = 1, int j = 1){
01150         width = j;
01151         length = i;
01152     }
01153     SparseArray(int i = 1 , int j = 1){
01154         width = j;
01155         length = i;
01156     }
01157 
01158     //Any better idea? i would like to unify the get and operator() functions.
01159     // Problem is that  operator() always passes a reference or creates one.
01160     template<class indexType>
01161     T& operator()(indexType i_, indexType j_){
01162         Int32 i = static_cast<Int32>(i_);
01163         Int32 j = static_cast<Int32>(j_);
01164         TinyVector<int,2> newShapew(i, j);
01165         typename std::map<TinyVector<int,2>, T, ShapeCmp>::iterator iter;
01166         TinyVector<int,2> newShape;
01167         return data[newShapew];
01168     }
01169 
01170     template<class indexType>
01171     const T get(indexType i_, indexType j_){
01172         Int32 i = static_cast<Int32>(i_);
01173         Int32 j = static_cast<Int32>(j_);
01174         TinyVector<int,2> newShape(i, j);
01175         if(data.find(newShape) == data.end()) return 0;
01176         else return data.find(newShape)->second;
01177     }
01178 
01179     //see documentation of mxCreateSparse and the mxGet functions to understand this.
01180     void mapToMxArray(mxArray * & in){
01181 
01182         int len = data.size();
01183         in = mxCreateSparse(width, length, len, mxREAL);
01184         int* jc = mxGetJc(in);
01185         int* ir = mxGetIr(in);
01186         double* pr = mxGetPr(in);
01187         if(len == 0){
01188             jc[0] = 1;
01189             return;
01190         }
01191         typename std::map<TinyVector<int,2>, T, ShapeCmp>::iterator iter;
01192         TinyVector<int,2> newShape;
01193         int ii = 0;
01194         int jj = 0;
01195         int curjc = -1;
01196         for( iter = data.begin(); iter != data.end(); ++iter ) {
01197             newShape = iter->first;
01198             ir[ii] = newShape[1];
01199             pr[ii] = iter->second;
01200             if(newShape[0]  != curjc){
01201                 curjc = newShape[0] ;
01202                 jc[jj] = ii;
01203                 jj++;
01204             }
01205 
01206             ii++;
01207         }
01208         jc[jj] = len;
01209     }
01210 
01211 };
01212 
01213 enum DataDimension {IMAGE = 2, VOLUME = 3};
01214 
01215 } // namespace matlab
01216 
01217 } // namespace vigra
01218 
01219 void vigraMexFunction(vigra::matlab::OutputArray, vigra::matlab::InputArray);
01220 
01221 #ifndef VIGRA_CUSTOM_MEXFUNCTION
01222 
01223 /*
01224     DO NOT Comment out this function. If you are using a
01225     custom mexfunction just #define VIGRA_CUSTOM_MEXFUNCTION
01226     before #including matlab.hxx.
01227 */
01228 void mexFunction(int nlhs, mxArray *plhs[],
01229                  int nrhs, const mxArray *prhs[])
01230 {
01231   try
01232   {
01233     vigra::matlab::InputArray inputs(nrhs, prhs);
01234     vigra::matlab::OutputArray outputs(nlhs, plhs);
01235 
01236     vigraMexFunction(outputs, inputs);
01237   }
01238   catch(std::exception & e)
01239   {
01240     mexErrMsgTxt(e.what());
01241   }
01242 }
01243 
01244 #endif /*CUSTOM_MEXFUNCTION*/
01245 
01246 
01247 #define VIGRA_CREATE_ENUM_AND_STD_MAP2(mapName, item1, item2) \
01248     const int item1 = 1;\
01249     const int item2 = 2;\
01250     std::map<std::string,int>  mapName;\
01251     mapName[#item1] = (int)item1;\
01252     mapName[#item2] = (int)item2;\
01253 
01254 
01255 #define VIGRA_CREATE_ENUM_AND_STD_MAP3(mapName, item1, item2, item3) \
01256     const int item1 = 1;\
01257     const int item2 = 2;\
01258     const int item3 = 3;\
01259     std::map<std::string,int>  mapName;\
01260     mapName[#item1] = (int)item1;\
01261     mapName[#item2] = (int)item2;\
01262     mapName[#item3] = (int)item3;\
01263 
01264 
01265 #define VIGRA_CREATE_ENUM_AND_STD_MAP4(mapName, item1, item2, item3, item4) \
01266     const int item1 = 1;\
01267     const int item2 = 2;\
01268     const int item3 = 3;\
01269     const int item4 = 4;\
01270     std::map<std::string,int>  mapName;\
01271     mapName[#item1] = (int)item1;\
01272     mapName[#item2] = (int)item2;\
01273     mapName[#item3] = (int)item3;\
01274     mapName[#item4] = (int)item4;\
01275 
01276 #define VIGRA_CREATE_ENUM_AND_STD_MAP5(mapName, item1, item2, item3, item4, item5) \
01277     const int item1 = 1;\
01278     const int item2 = 2;\
01279     const int item3 = 3;\
01280     const int item4 = 4;\
01281     const int item5 = 5;\
01282     std::map<std::string, int>  mapName;\
01283     mapName[#item1] = (int)item1;\
01284     mapName[#item2] = (int)item2;\
01285     mapName[#item3] = (int)item3;\
01286     mapName[#item4] = (int)item4;\
01287     mapName[#item5] = (int)item5;\
01288 
01289 #define VIGRA_CREATE_ENUM_AND_STD_MAP6(mapName, item1, item2, item3, item4, item5, item6) \
01290     const int item1 = 1;\
01291     const int item2 = 2;\
01292     const int item3 = 3;\
01293     const int item4 = 4;\
01294     const int item5 = 5;\
01295     const int item6 = 6;\
01296     std::map<std::string,int>  mapName;\
01297     mapName[#item1] = (int)item1;\
01298     mapName[#item2] = (int)item2;\
01299     mapName[#item3] = (int)item3;\
01300     mapName[#item4] = (int)item4;\
01301     mapName[#item5] = (int)item5;\
01302     mapName[#item6] = (int)item6;\
01303 
01304 #endif // VIGRA_MATLAB_HXX

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.9.0 (Tue Nov 6 2012)